pax_global_header00006660000000000000000000000064141026105150014505gustar00rootroot0000000000000052 comment=152cc58ee6a8213fbb36fbb7285d2358febb37af camlp5-rel8.00.02/000077500000000000000000000000001410261051500135405ustar00rootroot00000000000000camlp5-rel8.00.02/.gitignore000066400000000000000000000002001410261051500155200ustar00rootroot00000000000000*.o myconfig */.depend.bak local-install .tramp_history */.tramp_history */*/.tramp_history .merlin */.merlin */*/.merlin *.ppo camlp5-rel8.00.02/CHANGES000066400000000000000000001236541410261051500145460ustar00rootroot00000000000000 Camlp5 Version 8.00.02: -------------------- * [03 Aug 2021] updates to support OCaml 4.13.0 Camlp5 Version 8.00.01: -------------------- * [17 Jan 2021] No big changes, only bugfixes and minor ocaml 4.12.0 changes that should not break any code. Camlp5 Version 8.00: -------------------- * [26 Dec 2020] several changes * support ocaml 4.12 syntax: injective type-parameters and prefix-ops containing hash. * debug-printing via pa_ppx -- requiring 'pa_ppx.base' will load 'pa_ppx.deriving_plugins.show'-based pretty-printers for Camlp5's AST types. Camlp5 Version 8.00-alpha07: -------------------- * [18 Oct 2020] BIG change: the type of expressions (MLast.expr) is switched to using longidents instead of the old "ExAcc"/"ExUid" stuff. This is a vast improvement in correctness as well as allowing better support for things like "M.N.( ... expr ...)" The old quotation syntax <:expr< $e1$ . $e2$ >> is discontinued. Instead you should use: <:expr< $longid:li$ >>: for a module-path or constructor <:expr< $longid:li$ . ( $e$ ) >>: for a local-open <:expr< $e$ . $longid:li$ . $lid:id$ >>: for a qualified field-name, e.g. x.Location.txt <:expr< $e$ . $lid:id$ >>: for a simple field-name, e.g. x.txt Camlp5 Version 8.00-alpha06: -------------------- * [01 Oct 2020] multiple small changes * export "pa_macro_gram.cmo" as the findlib package "camlp5.macro_gram": this provides IFDEF support in grammars. * in Q_ast, add "stri" as a valid antiquotation for str_item. And add tests. * factored out base of Q_ast, so we can use it in PPX derivers that generate quotations for other types than Camlp5's AST Camlp5 Version 8.00-alpha05: -------------------- * [24 Sep 2020] add support for 4.11.0 quoted-extension, viz {%foo|argle|} and {foo bar|argle|bar} * [19 Sep 2020] multiple small changes * export more names from Reloc * in Q_MLast, allow Qast.Node to take a dotted name, e.g. Qast.Node "A.B.C" and convert it into an access-expression, so we can use quotations over types not in MLast. Camlp5 Version 8.00-alpha04: -------------------- * [01 Sep 2020] Add support for Ocaml 4.11.1. Support "#-types" with extended longidents (module-applications). Test support for same. Camlp5 Version 8.00-alpha03: -------------------- * [22 Aug 2020] Add support for Ocaml 4.10.1. Camlp5 Version 8.00-alpha02: -------------------- * [18 Aug 2020] fixed original-syntax pretty-printing bug in class-decl params. * [16 Aug 2020] added "-version" to succinctly print out camlp5 version (like "ocamlc --version"). Added "constructor" quotation to q_MLast and q_ast, we can pattern-match with quotations, on constructor-declarations. * [15 Aug 2020] fixed "-verbose" bug in mkcamlp5 (and updated doc) * [13 Aug 2020] rehabilitated q_ast parsing kit and verified that it works just as q_MLast does (for revised syntax). Still haven't done so original syntax (and it won't, since original syntax has ambiguities when introducing antiquotations everywhere). Also rehabbed the "test" tests, but not all of them work (e.g. "quot_o"). Changed revised syntax (only revised -- original syntax remains the same) of GADT declarations to allow them to be pattern-matched with quotations. Example: instead of type t = A : t1 -> t2 -> t use type t = A of t1 and t2 : t This allows quotations like type t = [ A of $list:args$ : $t$ ] ; * [05 Aug 2020] Fixed top/rprint so that in revised syntax toplevel mode, exceptions get printed out correctly. TODO: Devise a unit-test for this, and go thru and verify that it works for all "outcometree" types. * [01 Aug 2020] Added purely-internal "ppxprint" (PPX-derived printers for AST types) so we can use it to debug. It's disabled by default, so no external users should need to worry about it. To enable, build camlp5 with "BOOTSTRAPPED=1" as an extra toplevel make argument. TODO: add this to the "configure" script. * [30 Jul 2020] fixed parser lookahead-too-far bug in revised syntax. Input {|(F.f 1);|} was causing lookahead to the token after the semicolon. * [25 Jul 2020] add "extfold" to META. Move much documentation from README.md to Sphinx/RST docs. Add example of extending Ocaml syntax to tutorial. * [24 Jul 2020] update META to allow use of all syntax-extension kits with original syntax. Some of these will be breaking; we'll undo them as we find that they break (assuming nothing can be done to fix the breakage). Camlp5 Version 8.00-alpha01: -------------------- * [07 Jul 2020] Massive number of changes to support PPX extension/attribute syntax, PPX rewriters, and syntax changes thru Ocaml 4.10.0. Also support for Ocaml 4.11.0, but not for syntax changes therein (that'll come in the next release). It is fair to say that this release has lots of incompatibilities with the previous stream, hence the bump in major version number. Many camlp5 users will find that things continue to work; others will find that they do not, I'm happy to help them upgrade their code. I'll maintain the 7.xx stream of code as long as I can (in the face of Ocaml changes), but new function will appear here as part of 8.xx. I'll try to list big changes below: * New set of packages in META file, so you should be able to use camlp5 almost exclusively via ocamlfind (not having to resort to the camlp5{,r,o} commands). * New documentation in Sphinx/RST format (thanks to Kakadu@ !) and this is the documentation that will be updated, going forward. I'll keep the old docs around for the next few releases until the new docs are fully-updated and cleaned-up, but eventually they'll get deleted. * Support for all the syntax up to 4.10.0, including all PPX attributes and extensions, parsed, represented in parsetree, pretty-printed, passed properly to Ocaml compiler. Of course, all the syntax is supported in "original" syntax; with few exceptions, all of it is also supported in "revised" syntax. * Most of the places where Ocaml introduced module-prefixes (e.g. "M.N.(A e1 e2)") are now supported. The glaring exception is in *expressions*, and this will be fixed in a coming release. This means that instead of pattern-matching on (for instance) patterns to take apart a module-prefix, you pattern-match to extract a "longid" and that longid itself can be pattern-matched to reveal the module-identifiers. * Camlp5 version 7.11 added support for "blank module-binders" in all syntax locatinos where module-names can be introduced (to follow Ocaml's introduction of same), and also "empty" functor arguments and argument-types", viz: in struct-items: module _ = struct ... end module F = functor () -> struct ... end module F = functor (_ : sig ... end) -> struct ... end and many other locations (look in the Ocaml documentation for those locations). in signature-items: module _ : sig ... end This necessarily means that in places where there was a string (module-id binder), you'll now have a string option; in places where there was a "string * ctyp" (bound module-type) you'll have "(string option * ctyp) option". * This new version preserves compatibility with Ocaml versions >= 4.00.0, though new function (e.g. PPX syntax, is ONLY tested with ocaml version 4.10.0 and above). More precise: all pre-existing camlp5 function (module bugfixes and API changes) should work with all ocaml versions; new function only works with ocaml >= 4.10.0. * A breaking change to the Grammar API of lib/grammar.mli. This can only affect code that constructs grammar-rules programmatically, rather than by using the "pa_extend.cmo" syntax. So literally no code in camlp5 is affected. The only example I know of that is affected is the "elpi" package. Previously, a grammar-rule consisted in a tuple of a list of symbols, and an "action" (code). Now, it is a thruple of: a list of symbols, a hashcode (of the AST of the action), and the action. This change is necessary to allow left-factorization to work properly for, e.g. rules like [ [ OPT [ "foo" ] ; x = INT ] | [ OPT [ "foo" ] ; x = STRING ] ] because implicitly, the OPT symbol involves an action that returns "()". * a breaking change to the Plexing API of lib/plexing.mli. This can only affect code that defines its own lexer (for example, defining a new language wholly in camlp5). Please consult the definition of the type "Plexing.Location' for details. The only downstream package affected (that I know of) is "elpi". Camlp5 Version 7.12: -------------------- * [29 Apr 20] Added a new "topfind.camlp5" script that can be "#use"-ed just like "topfind"; it defines #camlp5o and #camlp5r commands (like topfind's #camlp4o and $camlp4r commands) * [29 Apr 20] upgrade to minimal support for Ocaml 4.11.0 (specifically 4.11.0+dev2-2020-04-22). This does not provide support for any new stuff in 4.11.0; indeed, stuff may break. This is just minimal "build and bootstrap" support. Camlp5 Version 7.11: -------------------- * [26 Mar 20] forgot to add that this supports ocaml version 4.10.0. added findlib packages for "camlp5.pr_o", "camlp5.pr_r" and "camlp5.pr_dump", which load the appropriate archives into the toploop and preprocessor. Added a "topfind.camlp5" file that can be "#use"ed instead of "topfind", and will provide the commands "#camlp5o" and "#camlp5r". * [29 Oct 19] Added compatibility with ocaml version 4.08.2. * [29 Oct 19] Added compatibility with ocaml version 4.09.1. * [03 Feb 20] Added compatibility with ocaml version 4.10+beta2. * This release supports blank module-names in binders as well as generative functors. Camlp5 Version 7.10: -------------------- * [24 Aug 19] Fixed problem of compatibility with ocaml versions less than 4.08, lost after camlp5 version 7.08, making compilation of camlp5 impossible. Due to dynamic loading. Camlp5 Version 7.09: -------------------- Camlp5 Version 7.08: -------------------- * [02 Aug 19] Updated for (incoming) ocaml version 4.10.0. * [02 Aug 19] Updated for ocaml version 4.09.0. * [27 Jun 19] Updated for ocaml version 4.08.1. * [27 Jun 19] Updated for ocaml version 4.08.0 (by github user madroach). * [27 Jun 19] Added raw string syntax (by Check Murthy). * [21 Dec 18] Fixed bug: in printer pr_o.cmo, comment did not get passed through after "let in". Camlp5 Version 7.07: -------------------- * [10 Oct 18] Changed '/bin/rm' into 'rm' in Makefiles. Can be changed by user by 'make RM=...'. * [08 Oct 18] Updated for ocaml version 4.07.2. * [19 Sep 18] Updated for ocaml upcomming version 4.08.0. * [18 Sep 18] Fixed bug: using camlp5 in ocaml toplevel, the errors locations in files (with #use) where not displayed. * [30 Aug 18] Updated for ocaml version 4.07.1 and upcomming version 4.08.0. Camlp5 Version 7.06: -------------------- * [17 Jul 18] Support nonrec type declaration (Kakadu). * [27 Jun 18] Updated for ocaml upcomming version 4.08.0. * [19 Jun 18] Add support for OCaml 4.07.0 * [19 Jun 18] Fix OPAM file [in particular avoid the filesystem deletion bug] * [06 Apr 18] Safe API for grammar extension (Pierre-Marie Pedrot). Camlp5 Version 7.05: -------------------- * [22 Feb 18] Fixed compilation failure when compiled with ocaml versions 3.08.0 to 4.02.4 due to the time when the constructor Pconst_integer was created (at ocaml version 4.03.0 actually). * [22 Feb 18] Added compatibility with (old) ocaml version 4.03.3. * [20 Feb 18] Changed "make install" and "make uninstall" so that they do nothing if "configure" had failed. Camlp5 Version 7.04: -------------------- * [19 Feb 18] Updated for ocaml version 4.06.1 and 4.06.2. * [02 Jan 18] Fixed missing treatment of native, 32 and 64 integers. Camlp5 Version 7.03: -------------------- * [20 Oct 17] Updated (again) for ocaml version 4.06.0. Camlp5 Version 7.02: -------------------- * [07 Oct 17] Updated for ocaml version 4.06.0. * [22 Jul 17] Now "a.[i] := b" generates a call to Bytes.set instead of String.set, as from ocaml version 4.02.0. * [18 Jul 17] Updated for ocaml future version 4.05.1. * [13 Jul 17] Compilation from OCaml version 4.00.0 now using parsetree distributed with OCaml (-I +compiler-libs), no more the one copied from OCaml sources (on ocaml_stuff directory). Set at "configure" time. (Not fully implemented: the magic numbers are still read in ocaml_stuff directory.) Is going to simplify Camlp5 update when new version of OCaml is released. * [11 Jul 17] Fixed problem of associativity in backtracking grammars, preventing Coq to compile with CAMLP5PARAM=f or b. Camlp5 Version 7.01: -------------------- * [26 Jun 17] Fixed bug in associativity of entry levels in extensible grammars; was introduced by an old experiment, resulting a failure in Coq test-suite/success/rewrite_strat.v. * [26 Jun 17] Fixed bug: compilation failed while using OCaml versions between 3.05 and 4.01.1, and jocaml versions. Camlp5 Version 7.00: -------------------- * [26 Jun 17] Release number is 7.00 instead of 6.18 because of big improvements on extensible grammars which can use now limited and full backtracking algorithms on demand. * [16 Jun 17] Entry.parse_token has been renamed Entry.parse_token_stream. * [04 Jun 17] Added limited backtracking (functional streams) to extensible grammars. Can be set with "Grammar.parse_algorithm Functional" or by setting the environment variable CAMLP5PARAM=f. * [01 Jun 17] Backtrack parsing seems to work well now. Camlp5 and Coq can be compiled using it by setting CAMLP5PARAM=b. * [31 May 17] Fixed bug: Entry.parse_token did not accept backtrack parsing. * [31 May 17] Fixed ocaml parsing for case of record {foo () with ...}. * [31 May 17] Fixed bug backtrack parsing for function Entry.of_parser. * [28 Apr 17] Updated for ocaml 4.04.2 which was missing. * [07 Apr 17] Updated for ocaml trunk 4.06.0 * [19 Feb 17] Fixed bug: locations of all identifiers were missing resulting of error messages giving "" as source file name and no line and column number in the source. * [04 Jan 17] Updated for ocaml trunk 4.05.0 * [09 Dec 16] Fixed bug: was not compatible with ocaml compiled with option -safe-string. * [09 Dec 16] Fixed bug: make uninstall did not take DESTDIR into account. * [07 Dec 16] Fixed bug virtual methods in signatures generated syntax tree of virtual val. Bug notified by Kakadu. Ex: "class foo : object method virtual bar : bool end" * [07 Dec 16] Fixed bug not separated idents were not allowed in 'let open' constructs. Bug notified by Kakadu. Ex: "let open Mod1.Mod2.Mod3 in ..." * [06 Dec 16] Fixed bug dumping module definitions with constraints. Bug notified by Kakadu. Ex: module type Item = sig type t end module type Sig = sig type t module Node : Item end module Make (S : Sig) : Sig with module Node = S.Node and type t = S.t * [06 Dec 16] Fixed bug extra option word during pr_dump for optional args. Bug notified by Kakadu. Ex: "class t : ?name:string -> object end" * [05 Dec 16] Fixed bug dumping of open object types. Bug notified by Kakadu. Ex: "type t = " * [05 Dec 16] Fixed bug dump parsetree without throughing away module type annotation. Bug notified by Kakadu. Ex: "module rec A : sig end = struct end" Camlp5 Version 6.17: -------------------- * [09 Sep 16] Added pretty print of type [< ... ] when ended with "> `ident". * [24 Jul 16] Added compatibility with ocaml 4.04.0 and 4.04.1. * [24 Jul 16] Added compatibility with ocaml 4.03.1. Camlp5 Version 6.16: -------------------- * [28 Apr 16] Fixed problems of compatibility with previous versions of ocaml. Camlp5 Version 6.15: -------------------- * [23 Jan 16] Fixed bug on optional types (ocaml 4.02). * [15 Jan 16] Fixed bug on methods wrongly interpreted as vals. * [05 Jan 16] Updated for ocaml trunk 4.03.0 (git version be2a7e2f830911b331657b8cfa462f5219dfec5b) * [26 Nov 15] Updated again for ocaml trunk current version (4.03.0). * [23 Sep 15] Updated for ocaml trunk current version (4.03.0). Camlp5 Version 6.14: -------------------- * [30 Jul 15] Updated for ocaml version 4.02.3 and 4.02.4 Camlp5 Version 6.13: -------------------- * [20 Apr 15] Accept 'fun/try' case list like the change of 22nd Apr 13 on 'match' in revised syntax, allowing them to write "|" .. "end" or "[" .. "]", both being accepted. * [12 May 15] Updated for ocaml version 4.02.2 Camlp5 Version 6.12: -------------------- * [17 Apr 14] Updated for ocaml trunk (4.02.0) svn rev 14621. * [14 Apr 14] Updated for ocaml version 4.01.1. * [19 Dec 13] Dummy line numbers are now 1 instead of -1 to prevent errors that sometimes happen later at assembling phase. * [19 Dec 13] Fixed problem in top/Makefile when OCLIBDIR contains spaces. * [06 Sep 13] Added flag Grammar.utf8_print to print grammars entries (with Grammar.Entry.print) displaying strings in utf-8 (default: True). Usefull e.g. for Coq in command 'Print Grammar constr' when using utf8. * [27 Aug 13] Fixed bug in normal syntax: "let f { x } = ...", "{ x }" and "let open ..." were refused. Camlp5 Version 6.11: -------------------- * [22 Jul 13] Updated for ocaml version 4.01.0 * [02 Jul 13] Added 'MLast.loc_of_with_constr'. * [02 Jul 13] Fixed bug toplevel with revised syntax; "= 'a" was missing in output in that example: # module type A = sig module type S = 'a; end; module type A = sig module type S; end * [02 Jul 13] Now accept lowercase ident for module types, like ocaml does. Accepted also in revised syntax. Camlp5 Version 6.10: -------------------- * [19 Jun 13] Updated for ocaml version 4.01.0 * [14 Jun 13] (experimental) Now, in revised syntax, a "." followed by a newline is interpreted as a ";", allowing to end phrases with ".". Drawback: will syntax error when writing a record/module access in two lines ending the first one with "." like: foo. bar Camlp5 Version 6.09: -------------------- * [22 Apr 13] Accept now "match with | | ... end" in revised syntax, with a required "|" in the first case, as alternative syntax for match. * [19 Apr 13] Added function 'Pcaml.value greek_ascii_equiv' giving an ascii equivalent to a greek (utf8) letter representing a type parameter. E.g. 'a' for 'α', 'b' for 'β', and so on. * [19 Mar 13] Fixed bug no locations built in some cases of constructors. * [15 Mar 13] Updated for ocaml version 4.00.2. * [13 Mar 13] Fixed bug: in toplevel, the highlighting of errors did not work. * [13 Mar 13] Added option '-dquot' to specify the default quotation name. and the ability to use "#option" directive with two parameters. Therefore, we can use either (e.g.): -dquot "expr" in the command line of camlp5 or #option "-dquot" "expr" inside a file. Camlp5 Version 6.08: -------------------- * [06 Mar 13] Now 'make' displays a message how to compile, instead of doing 'make out'. Old behaviour of 'make' must be now 'make out'. * [28 Feb 13] Now accept identifiers starting with a greek letter as variable names. * [28 Jan 13] Fixed bug: DEFINE FOO=32 while using pa_macro.cmo did not work due to a bad order in grammar insertion. * [08 Oct 12] Fixed bug: parsing greek letters as type variable in constructor declaration did not work when building Camlp5. Camlp5 Version 6.07: -------------------- * [12 Sep 12] Added compatibility with OCaml 4.00.1. * [06 Jun 12] Fixed bug: open record patterns {a=b;c=d;_} did not work. Camlp5 Version 6.06: -------------------- * [01 Jun 12] Added compatibility with OCaml 4.00.0 and (incoming) 4.01.0. * [18 Mar 12] Fixed bug in pr_o: [(let module M = ... in x); y] was displayed without parentheses. * [14 Mar 12] Added compatibility with OCaml 3.12.2. * [02 Mar 12] Added compatibility with JoCaml 3.12.0 and 3.12.1. * [02 Mar 12] Completed with all JoCaml statements in ocaml syntax. Todo: pretty print. Camlp5 Version 6.05: -------------------- * [02 Mar 12] Added compatibility with JoCaml trunk. * [02 Mar 12] Added option -oname in configure to change ocaml command name. The bytecode compiler, native compiler and bytecode runtime are respectively c, opt and run. The default is 'ocaml', implying that the executables are ocamlc, ocamlopt and ocamlrun. Setting it to 'jocaml', fo example, use jocamlc, jocamlopt and jocamlrun. Camlp5 Version 6.04: -------------------- * [01 Mar 12] Added option -name in configure to change command name useful to have transitional and strict versions installed with different names. Default: camlp5. * [01 Mar 12] The default mode at configuration time is now 'strict'. Camlp5 Version 6.03: -------------------- * [09 Jan 12] Updated compatibility with OCaml trunk version (3.13.0). Camlp5 Version 6.02.3: ---------------------- * [20 Oct 11] Updated compatibility with OCaml current version 3.13.0. * [20 Sep 11] Added missing syntax "_" in ending patt records (rev: "_ = _"). * [20 Sep 11] Fixed bug pattern -1L was refused in normal syntax. * [21 May 11] Fixed bug impacting files using q_ast.cmo extension (bad ast). * [03 May 11] Fixed bug: lexeme errors in revised syntax + utf8. * [24 Mar 11] Fixed bug: M.(a+b) was refused in normal syntax. * [16 Mar 11] Fixed bug: incorrect compilation of label patterns of the form ~a:b (or ~{a = b} in revised syntax) in class declarations. * [16 Mar 11] Fixed bug: error while printing label patterns ~a:b with pr_o.cmo (error message "labels not pretty printed (in patt)"). Camlp5 Version 6.02.2: ---------------------- * [15 Mar 11] Fixed bug: bad AST generated for class identifier prefixed by a module. * [15 Mar 11] Fixed differences of locations between OCaml and camlp5o (e.g. in .annot files) * [17 Feb 11] Pretty module now considers strings as utf8 encoded (impacts computation of strings lengths). * [04 Feb 11] Revised syntax: completed syntax multi labels, ~{x=y; z=t} (equivalent to ~{x=y} ~{z=t}) in patterns (in 6.02.1 was implemented only in expressions). * [28 Jan 11] Added installed module 'Reloc': relocations and equalities over syntax trees. * [26 Jan 11] Fixed bug in camlp5o.opt: did not accept '$' as token. * [18 Jan 11] Fixed bug: private flags in type manifest were not correctly treated. * [06 Dec 10] Fixed bug in pr_o.cmo: label expressions were not correctly pretty printed: f ~a gave f a. Camlp5 Version 6.02.1: ---------------------- * [05 Dec 10] In module Grammar.Entry.print, added extra parameter ppf to print in other formatter than (the default) stdout. * [21 Nov 10] Revised syntax: added syntax multi labels, ~{x=y; z=t} equivalent to ~{x=y} ~{z=t} * [16 Nov 10] Updated compatibility with OCaml version 3.13.0-gadt. Camlp5 Version 6.02.0: ---------------------- * [16 Nov 10] Fixed bug in pa_o.ml: !foo.(bar) was interpreted as !(foo.(bar)) instead of (!foo).(bar). Fixed compilation bug in pa_o.ml in transitional mode. * [16 Nov 10] Added parsing and printing utf8 greek letters and arrow in revised syntax. Camlp5 Version 6.02: -------------------- * [12 Nov 10] Added compatibility with OCaml GADT version. * [12 Nov 10] pa_macro: added ability to use ELSIFDEF in match cases (the ending ELSE part being still optional). * [08 Nov 10] Fixed bugs 1/ in pa_o: !Foo.bar was interpreted as (!Foo).bar instead of !(Foo.bar) 2/ in top/camlp5_top.cma: the file ast2pt.cmo was missing. Camlp5 Version 6.01: -------------------- * [03 Nov 10] Added in revised syntax for labels ~{lab x = y} as shortcut for ~{lab = fun x -> y}. * [30 Oct 10] Fixed bug in 'configure': option -libdir did not work. Camlp5 Version 6.00: -------------------- * [28 Oct 10] Updated compatibility with OCaml trunk version (3.13.0). * [01 Oct 10] Make compilation with "make -j" (parallel make) work. * [29 Sep 10] Fixed bug when using constructors named 'True' and 'False'. * [24 Sep 10] Fixed many bugs of parsing comments (typically about quotes). * [23 Sep 10] Fixed bug in pretty printing comments containing '"'. * [22 Sep 10] Fixed bug bad result of unary minus functions. * [22 Sep 10] Fixed bug in printing parameters of types of 'with constraint'. * [22 Sep 10] Fixed bug in revised syntax for class_types. Now application. does not need parenthesis any more (like for other entries of that kind). * [19 Sep 10] In grammars, added list with separator with optional ending separator (LIST0 .. SEP OPT_SEP and LIST1 .. SEP OPT_SEP). * [19 Sep 10] Completed missing statements in particular in objects, classes, and first class modules. * [08 Sep 10] Added option '-flag O' of pr_r.cmo and pr_o.cmo which add location comments in the output. * [08 Sep 10] Added new chapters in the documentation: - Directives - Redefining OCaml syntax * [08 Sep 10] Fixed option '-flag E' (equilibrate cases) of pr_r.cmo and pr_o.cmo which did not work. * [06 Sep 10] Changed revised syntax of 'inherit something [params]' into 'inherit [params] something' (like in normal syntax). * [06 Sep 10] Added missing statements: - 'module type of' as module type, - '(module ... : ...)' as expression, - '(val ...)' ('value' in revised syntax) as module expression. * [02 Sep 10] Added directive "#option" (in files, not in toplevel). * [02 Sep 10] pa_macro.cmo: phrases inside IFDEF statements now are implementation or interface items, which means: - ability to use directives which are, therefore, conditional. - in revised syntax must end with semicolon (incompatibility with previous versions of Camlp5 where these semicolons are syntax errors). - in revised syntax, ability to put several phrases without having to use "declare .. end". * [30 Aug 10] pa_macro.cmo: added ability to use ELSIFDEF and ELSIFNDEF in expressions, structure items and signature items. * [27 Aug 10] Fixed bug in pa_macro.cmo A AND B computed B AND B. * [26 Aug 10] Fixed wrong behaviour: char '"' was printed '\"'. * [25 Aug 10] Added option -no-opt in configure, not to use .opt versions of OCaml compilers. * [20 Aug 10] Added compatibility for OCaml version 3.11.3. * [18 Aug 10] Added function "get" in library module "Ploc", and a statement "lprintf" similar to "pprintf" added by the syntax extension kit "pa_pprintf.cmo". Camlp5 Version 5.15: -------------------- * [09 Aug 10] Updated compatibility for OCaml current version 3.12.1. * [09 Aug 10] Upgraded compatibility for OCaml released version 3.12.0. * [29 Jul 10] Added ability to write AST quotations with a colon before the '<' (e.g. "<:expr:< foo >>") which, in pattern position, generates a binding of the variable "loc" at the top node: 1/ normal usage (still working): "fun [ <:expr< x >> -> 0 ]" which is equivalent to: "fun [ MLast.ExLid _ (Ploc.VaVal "x") -> 0 ] 2/ new usage: "fun [ <:expr:< x >> -> 0 ]" which is equivalent to: "fun [ MLast.ExLid loc (Ploc.VaVal "x") -> 0 ] * [21 Jun 10] Added compatibility for OCaml trunk version 3.13.0. * [29 Apr 10] Fixed bug in pr_depend.cmo: a.B.c did not add module B. Camlp5 Version 5.14: -------------------- * [28 Apr 10] Updated compatibility for OCaml current version 3.12.0. * [31 Mar 10] Fixed bug in pr_o.cmo: error message when using "#use" Camlp5 Version 5.13: -------------------- * [02 Nov 09] Added compatibility with OCaml 3.11.2. * [02 Nov 09] Updated compatibility with OCaml 3.12.0. * [30 Jul 09] Added 'lazy' patterns (added in OCaml version 3.11). * [09 Jun 09] Fixed bug in pr_r.cmo: did not always break after "in" (in "let..in" statements) even with -flag l. * [08 Jun 09] Fixed bug in pr_r.cmo: missing case "#use" for structure and signature items. Camlp5 Version 5.12: -------------------- * [23 May 09] Added compatibility with OCaml 3.11.1. * [31 Dec 08] In macros (pa_macro.cmo): - added ability to use IFDEF and IFNDEF for record labels declarations. Camlp5 Version 5.11: -------------------- * [19 Dec 08] Added compatibility with OCaml 3.12.0. Camlp5 Version 5.10: -------------------- * [16 Oct 08] Added compatibility with OCaml 3.11.0. * [01 Aug 08] Added flag "Plexer.utf8_lexing" to specify that the lexers built by "Plexer.gmake ()" must consider the input as utf-8 encoded. Camlp5 Version 5.09: -------------------- * [05 Jun 08] Changed all '#!/bin/bash" in shells scripts into '#!/bin/sh' and changed all $(...) into `...` because there are compatibilities problems according to Unix versions. * [31 Mar 08] Fixed bug: "let f ~_x () = ()" generated syntax error. * [31 Mar 08] Fixed bug: "x $ y" generated syntax error (normal syntax). * [02 Jan 08] Added compatibility with OCaml 3.10.3. Camlp5 Version 5.08: -------------------- * [08 Feb 08] Fixed bug in normal syntax: a.{x,y} (access to big array) was interpreted as a.{(x,y)}. * [22 Jan 08] Added missing cases in printers pr_o and pr_r which displayed the message "unable to print ...". * [02 Jan 08] Added compatibility with OCaml 3.09.4 and 3.10.2. * [21 Jan 08] Fixed bug under windows: the file META could not be build if the library path name contained colons. * [13 Jan 08] Added missing man page for camlp5sch (link to the same man page as camlp5). * [05 Jan 08] Added "pr_extprint.cmo", printer rebuilding EXTEND_PRINTER statements in their original syntax. * [05 Jan 08] Fixed bug in EXTEND_PRINTER statement: the match cases with "when" did not work. Camlp5 Version 5.07: -------------------- * [02 Jan 08] Added "pprintf" statement to use the Camlp5 pretty print system more easily and shortly. * [27 Dec 07] Added function [Grammar.Entry.parse_all] returning the list of all solutions when using the parsing algorithm [Backtracking]. Camlp5 Version 5.06: -------------------- * [19 Dec 07] Upgraded to add compatibilitly with OCaml version 3.10.1. Camlp5 Version 5.05: -------------------- * [17 Dec 07] Added function [Pcaml.quotation_location] returning the location of the quotation in the source in the context of a quotation expander. * [04 Dec 07] Added generation of file META for ocamlfind in directory etc (built but not installed). * [28 Nov 07] Upgraded to reflect changes done in parse tree in current OCaml (version 3.11+dev6). * [27 Nov 07] Fixed bug in installation. Some files where installed in the bin directory instead of lib directory. * [27 Nov 07] Fixed bug in parsing comments: comments containing '\' where incorrectly parsed. Camlp5 Version 5.04: -------------------- * [24 Nov 07] Fixed bug in install under MSVC Windows: object and library files were not installed (using wrong extensions). * [24 Nov 07] Fixed bug under Windows: line numbers in error messages were wrong (twice the normal value). * [24 Nov 07] Added ability to change the parsing algorithm of extensible grammars, with the function "Grammar.set_algorithm" whose parameter can be "predictive" or "backtracking". * [22 Nov 07] Added backtracking parsers. Functions defined in the module Fstream (already containing functional streams and parsers). Syntax added in pa_fstream.cmo (already containing syntax for functinal streams and parsers). The new syntax uses "bparser" instead of "fparser" and a backtracking parser returns, together with its result and its remaining stream, the continuation to compute the next solution. Camlp5 Version 5.03: -------------------- * [20 Nov 07] Added commands mkcamlp5 and mkcamlp5.opt to build camlp5 executables with predefined loaded modules. Added installation of ocpp with name ocpp5, instead of just ocpp. * [19 Nov 07] Added more installed cmx and cmxa files to allow building native code linking of all combinations of Camlp5. * [14 Nov 07] Fixed bug in pr_o.cmo: failed with printing "{a.(i) with ...}". * [14 Nov 07] Fixed bug under Windows for the printers (pr_o.cmo, pr_r.cmo and pr_scheme.cmo): extra return character '\r' was added at end of lines. * [09 Nov 07] Fixed bug in camlp5o.opt in strict mode: did not parse correctly, in particular type expression (the version "camlp5o" without ".opt" however worked). * [29 Oct 07] Added [Pcaml.inter_phrases], a way to set, by program, the value of the "-sep" option of the printers kits. * [28 Oct 07] Fixed bug in pa_fstream.cmo (functional parsers): the keyword after "match with" was "parser" instead of "fparser" and its code was wrong. * [27 Oct 07] Added a default lexing buffer (in module [Plexing]) for pa_lexer.cmo: then, the programmer does not need to write it any more. Camlp5 Version 5.02: -------------------- * [14 Oct 07] Changed 'pa_lex.cmo' into 'pa_lexer.cmo' with a different syntax (see the documentation). * [14 Oct 07] In the EXTEND statement, added "LIKE s" as possible level position to specify a level containing a rule containing "s" in its keywords or tokens. * [11 Oct 07] Rewritten parsers and printers in Scheme syntax. Deleted old module Spretty. Camlp5 Version 5.01: -------------------- * [06 Oct 07] Fixed bug in grammars: there was a parsing confusion with entries with qualified names with same final identifier, resulting bad results. Example: (qualified names "Prim.ident" and "Constr.ident" have the same final identifier "ident"). EXTEND Prim.ident: [ [ ... ] ]; Constr.ident: [ [ ... ] ]; END; * [05 Oct 07] In Scheme syntax (pa_scheme.cmo), added "type*" (symmetric to "define*") and "exceptionrebind". * [04 Oct 07] Added flag C in pr_r.cmo and pr_o.cmo to add comments inside phrases (default = True). * [01 Oct 07] Added flag E in pr_r.cmo and pr_o.cmo to ask to equilibrate cases in 'match', 'if', 'parse', 'EXTEND' statements, i.e if one case does not fit on the line, all cases must be cut (default = False). * [01 Oct 07] Added module "Diff" in the library (general comparison of two arrays). Implemented with the same algorithm as the Unix 'diff' command. * [01 Oct 07] Fixed bug in pa_o.cmo (normal syntax) introduced in version 5.00. The example: "function Atom atext as cur :: tl' -> 0" did not parse, printing the error "incorrect alias pattern". Camlp5 Version 5.00: -------------------- * In Camlp5 compiled distributions, there are now two modes. If one wants to compile Camlp5, the 'configure' script can select the mode: The two modes are: - transitional mode: the syntax tree is compatible with the previous version; users don't have to change their programs, but in the syntax tree quotations introduced by the new parsing kit 'q_ast.cmo', the antiquotations are not available. - strict mode: the syntax tree is not compatible with the previous version. The user programs may compile without change, but may not. It depends on the fact that these programs use the syntax tree with their constructors forms instead of their quotation forms. There is a new feature: the syntax tree quotations in user syntax, introduced by the new parsing kit 'q_ast.cmo". * [25 Sep 07] Fixed bug: if parsing error at end of file, the error message printed a bad line number. * [17 Sep 07] Added [Ploc.call_with], a pervasive function. * [15 Sep 07] Added 'q_ast.cmo': this is the syntax tree quotations in the current syntax, including the possible user syntax extensions. The antiquotations work only in 'strict' mode, not in 'transitional' mode. * [15 Sep 07] In module Pcaml, added grammar entries 'ipatt', 'match_case', 'constructor_declaration', 'with_constr', 'poly_variant'. * [09 Sep 07] In macros (pa_macro.cmo): - changed parameters syntax: now in curried form instead of parentheses, - added ability to define macro type expressions in signatures, e.g.: DEFINE V t = t -> t - added ability to use IFDEF and IFNDEF for constructors declarations and matchs cases. * [08 Sep 07] Fixed bug in normal syntax (pa_o.cmo): class foo : ?foo:unit -> bar type foo = ?bar: unit -> unit;; were accepted but not with space(s) after the colon: class foo : ?foo: unit -> bar type foo = ?bar : unit -> unit;; * [06 Sep 07] Fixed problem of bad errors locations in Lisp and Scheme syntaxes. * [01 Sep 07] Renamed modules Stdpp into Ploc and Token into Plexing. Changed the names of some of their definitions. Backward compatibility assumed. * [31 Aug 07] For packagers: added DESTDIR in Makefiles to allow installation in fake root directories. Usage: make install DESTDIR=fake-root-dir Camlp5 Version 4.08: -------------------- * [] Updated documentation. * [30 Aug 07] Added IFDEF macros for signatures (.mli files). * [26 Aug 07] Added left factorization for consecutive rules of parsers (and lexers). * [21 Aug 07] Added equality functions over syntax trees in module Pcaml. * [21 Aug 07] Improved compiled version (camlp5o.opt) to add the fact that the grammar is LL(n) for rules starting with n terminals. * [20 Aug 07] Updated library interface comments. * [19 Aug 07] Added option -define with 'pa_macro.cmo' which prints the predefined macros and exit. * [16 Aug 07] Added pa_extprint.cmo, a new syntax for extensible pretty printers adding a statement EXTEND_PRINTER (cf files pr_r.cmo and pr_o.ml as examples). Added library module Eprinter. Changes (simplifications) in interfaces of Pcaml for the printers. Camlp5 Version 4.07: -------------------- * [02 Aug 07] Fixed bug: option -o did not work for pr_r.cmo and pr_o.cmo (was always stdout). * [01 Aug 07] In EXTEND statement, added symbol FLAG: like OPT but return a boolean value. The antiquotation kind "flag" must be used in this case, but the "opt" still works by compatibility. * [30 Jul 07] Fixed bug in normal syntax: let C x = C 1 was not accepted. * [30 Jul 07] Changed pretty printing *normal* syntax: let C x = .. printed like that, *not* transformed into let x = match .. with C x -> x. Camlp5 Version 4.06: -------------------- * [25 Jul 07] Fixed bug: in normal syntax, the declaration of a constructor named "True" or "False" did not work. * [25 Jul 07] While expanding stream parsers, transform unused bound variables into wildcards to prevent compiler warnings. * [21 Jul 07] Fixed bug in normal syntax and printing of normal syntax: "poly type" was accepted with revised syntax, i.e. with "!" at beginning and displayed like it. Fixed also the printing of abstract module type which was not implemented. Added printing syntax of fun binding fof class parameters. * [20 Jul 07] Added revised syntax for bigarrays (same than normal syntax) and pretty print them in their initial syntax. * [18 Jul 07] In Grammar.Entry.print, local entries are displayed with a star character "*". * [18 Jul 07] In Grammar module, added type 'parsable', functions 'parsable' and 'Entry.parse_parsable' like for the functorial interface. Camlp5 Version 4.05: -------------------- * [16 Jul 07] Fixed bug in normal syntax: optional semicolon was no more accepted at end of stream patterns. * [16 Jul 07] Fixed syntax problems with "~id:" and "~id :" (with a space). Camlp5 Version 4.04: -------------------- * [11 Jul 07] Renamed application as "camlp5". * [11 Jul 07] Fixed compilation problems with ocaml version 3.08.1. Camlp4s Version 4.03: --------------------- * [10 Jul 07] Added argument "-name" in "configure" to specify another name of commands and libraries (default = camlp4). E.g. "configure -name camlp5" will build "camlp5", "camlp5r", "camlp5o", "camlp5.1", and so on, and the library directory will be installed in ocaml library directory as name "camlp5". * [10 Jul 07] Deleted command "mkcamlp4" which seems not to work any more. This will be fixed in a future version. Camlp4s Version 4.02: --------------------- * [08 Jul 07] Added missing compatibility with ocaml 3.10.0 * [05 Jul 07] Rebuilt pretty printers with new pretty printer module * [27 Jun 07] Added private flag in type declarations and with constraints * [21 Jun 07] Added "let..in" in parsers * [14 Jun 07] Added html documentation for: - the "extfun" statement - the "fparser" statement - the "lexer" statement - the "parser" statement - the "#pragma" directive - the module Pretty - the new pretty print in Camlp4 (using Pretty and "extfun") * [14 Jun 07] Library module Sformat renamed Pretty. The first parameter of the function horiz_vertic is now a function of type "unit -> 'a". * [31 May 07] Quotation "row_field" renamed "poly_variant". * [03 May 07] Fixed bug in pr_o: did not print "let f ?a = ()". Camlp4s Version 4.01: --------------------- * [27 Apr 07] Added compatibility with ocaml 3.11 Camlp4s Version 4.00: --------------------- * [31 Jan 07] Added a new syntax, "lexer", to write parsers of characters in a shorter way. New syntax extension "pa_lex.cmo". * [26 Jan 07] Deleted "LOCATE" lexing token kind and associated parsing stuff. Seems to be an old thing never used. * [20 Jan 07] Added "lookahead" stream pattern component kind. syntax ::= "?=" list lookhd_patt sep_by "|" lookhd_patt ::= "[" list pattern sep_by ";" "]" Checks the first stream elements against the pattern, without removing them from the stream (but possibly unfreezing them), continues the stream pattern if ok, fails (Stream.Failure or Stream.Error depending on the position of the component) if not. If there are more than one lookahead pattern, they must be of the same length. Examples in lib/plexer.ml. * [31 Dec 06] Added the ability to add "!" (in Revised syntax) or "?!" (in normal syntax) after a stream parser component to hint the preprocessor that the called parser cannot fail (which must be true, but not checked) which allows shorter code. E.g. parser [: x = f; y = g ! :] -> (x, y) This example is equivalent to: parser [: x = f; s :] -> let y = g s in (x, y) * [19 Dec 06] Added "pa_pragma.cmo" adding the directive "#pragma " which executes in the context of the preprocessor. * [16 Dec 06] Added ability to add directives: "Pcaml.add_directive". * [05 Dec 06] Fixed old bug: "camlp4 foo/bar.cmo" now searchs from the current directory (i.e in its subdirectory "foo"), instead of searching in the path. Before, we had to write "camlp4 ./foo/bar.cmo". * [01 Dec 06] In "pa_macro.cmo", the expression after IFDEF can use the infix operators OR and AND, the prefix one NOT and expressions between parentheses. * [01 Dec 06] The same distribution can compile with several versions of OCaml. After "./configure", the good version of OCaml interfaces are selected. * [01 Dec 06] The type "location" is now abstract. Defined in stdpp.mli. * [01 Dec 06] First distributed version; started from old camlp4 version 3.06 and updated. camlp5-rel8.00.02/DEVEL000066400000000000000000000205351410261051500143270ustar00rootroot00000000000000Information for developpers OVERVIEW Although the sources of camlp5 are written in camlp5 syntaxes, the distribution contain no 'magic' binary file for the first compilation. This first compilation can be done thanks to a version of the core of camlp5 written in pure ocaml syntax. Once this 'core' is compiled, all sources in revised syntax with syntax extensions can be compiled. COMPATIBILITY This distribution of camlp5 is compatible with several versions of ocaml. The problem is about the definition of ocaml syntax trees which may change from a version of ocaml to another. Since ocaml does not install the sources nor the compiled versions of its syntax tree, a copy of the necessary source files, borrowed from the source of the ocaml compiler has been done in the directory 'ocaml_stuff', in subdirectories with the ocaml version number. If the present distribution of camlp5 is not compatible with the version of ocaml you have (the command 'configure' tells you), it is possible to add it. For that, you need the sources of the ocaml distribution you have. Once done, after a 'configure' telling you that it is not compatible, do: make steal OCAML_SRC= This creates a new directory in 'ocaml_stuff' with sources of the syntax tree of your ocaml compiler. If you want to check that the sources of the syntax tree of ocaml are up-to-date (e.g. if this is the current ocaml developpement), do: make compare_stolen OCAML_SRC= The compatibility is also done with the file 'lib/versdep.ml', which is a module containing miscellaneous features depending to the version of OCaml. In the directory 'ocaml_src' which contains the pure OCaml sources of the Camlp5 core (see chapter TREE STRUCTURE below), there are as many versions of this files as versions of OCaml. They are named '.ml' in the directory 'lib/versdep'. If you are adding a new version of OCaml, you need this file. As a first step, make a copy from a close version: cd ocaml_src/lib/versdep cp .ml .ml Then, you can redo "configure" and do "make core". If the file 'ocaml_src/lib/versdep.ml' has a compilation problems, fix them and to 'make core' again. Later, the same file 'lib/versdep.ml' in camlp5 syntax may have similar compilation problem. This file is in one examplary, thanks to IFDEF used here or there. While compiling with some specific version of ocaml, this file is compiled with 'OCAML_vers' defined where 'vers' is the version number form the beginning to the first space or charcter '+' with all dots converted into underscores. For example, if your ocaml version is 7.04.2+dev35, you can see in the compilation process of versdep.ml that OCAML_7_04_2 is defined, and you can add statements defined by the syntax extension 'pa_macro.cmo', for example IFDEF OCAML_7_04_2. Add statements like that in 'lib/versdep.ml' to make it compile. TREE STRUCTURE The directory 'ocaml_src' contains images in pure ocaml syntax of the directories odyl lib main and meta. This allow to create a core version of camlp5 from only the ocaml compiler installed. You can decompose the building of the camlp5 core into: 1. make library_cold just makes the directory 'ocaml_src/lib' and copy the cmo and cmi files into the directory 'boot' 2. make compile_cold makes the other directories of ocaml_src 3. make promote_cold copies the executables "camlp5", "camlp5r" and the syntax extensions (cmo files) into the directory 'boot' From that point, the core camlp5 is in directory 'boot'. The real sources in the top directories odyl lib main and meta, which are written in revised syntax with some syntax extensions (grammars, quotations) can be compiled. To achieve their compilation, you can do: make core Or to compile everything do: make all or just: make Notice that doing "make core" or "make all" from scratch (after a make clean), automatically start by making the core files from their pure ocaml versions. FAST COMPILATION FROM SCRATCH ./configure make clean core compare make coreboot make all opt opt.opt TESTING CHANGES 1. do your changes 2. do: make core compare if it says that the bootstrap is ok, you can do: make all make opt make opt.opt otherwise, to make sure everything is ok, first do: make coreboot sometimes two bootstraps ('make coreboot' twice) are necessary, in particular if you change things in the directory 'lib'. It is even possible that three bootstraps are necessary. If things goes wrong, it is possible to return to the previous version by typing: make restore clean_hot then you can change what is necessary and continue by typing: make core and test the bootstrap again: make coreboot After several bootstraps (by 'make coreboot' or 'make bootstrap'), many versions are pushed in the directory 'boot' (you can type 'find boot -type d -print' to see that). If your system correctly bootstraps, you can clean that by typing: make cleanboot which keeps only two versions. (The command 'make clean' also removes these stack of versions.) BEFORE COMMITTING YOUR CHANGES Make sure that the cold start with pure ocaml sources work. For that, do: make compare_sources | less This shows you the changes that would be done in the ocaml pure sources of the directory ocaml_src. To make the new versions, do: make new_sources make promote_sources Notice that these pure ocaml sources are not supposed to be modified by hand, but only created by the above commands. Besides, their sources, although pretty printed, are sometimes not easy to read, particularly for expanded grammars (of the statement 'EXTEND'). However, if these sources do not compile, due to changes in the ocaml compiler, it is possible to edit them. In this case, similar changes may have to be done in the normal sources in revised syntax. After doing 'make new_sources' above, and before doing 'make promote_sources' below, it is possible to do 'make untouch_sources' which change the dates of the new created files with the dates of the old files if they are not modified. This way, the "svn commit" will not have to compare these files, which may have some importance if you network is not fast. The 'make new_sources' builds a directory named 'ocaml_src.new'. If this directory still exists, due to a previous 'make new_sources', the command fails. In this case, just delete it (rm -rf ocaml_src.new) without problem: this directory is not part of the distribution, it is just temporary. The 'make clean_sources' deletes old versions of ocaml_src, keeping only the last and the before last ones. The command: make bootstrap_sources is a shortcut for: make new_sources make untouch_sources make promote_sources make clean_sources If there are changes in the specific file 'lib/versdep.ml', do also: make compare_all_versdep and possibly: make bootstrap_all_versdep because this file, in 'ocaml_src/lib/versdep' directory has different versions according to the ocaml version. After having rebuilt the pure ocaml sources, check they work by rebuilding everything from scratch, starting with "configure". IF YOU CHANGE THE MAIN PARSER If you change the main parser 'meta/pa_r.ml', you may check that the quotations expanders of syntax tree 'meta/q_MLast.ml' match the new version. For that, do: cd meta make compare_q_MLast If no differences are displayed, it means that 'q_MLast.ml' is ok, relatively to 'pa_r.ml'. Otherwise, if the displayed differences seem reasonable, update the version by typing: make bootstrap_q_MLast Then returning to the top directory, do 'make core compare' and possibly 'make coreboot' (one of several times) to check the correctness of the file. And don't forget, if you want to commit, to re-create the pure ocaml sources like indicated above. camlp5-rel8.00.02/ICHANGES000066400000000000000000000103011410261051500146370ustar00rootroot00000000000000Internal, very small, undocumented, or invisible changes ******************************************************** Camlp5 Version 6.12: -------------------- * [20 Jan 14] Removed W3C icon image (in documentation) that should not be in Camlp5 distribution (violates Debian guidelines, in particular). Camlp5 Version 6.02.1: ---------------------- * [05 Dec 01] Fixed pb in 'make bootstrap_sources': failed if it was not a CVS working directory. Camlp5 Version 6.02: -------------------- * [12 Nov 10] In 'make steal' (resp. 'make compare_stolen'), build (resp. compare) now 'config.ml' with 'utils/config.mlp' instead of 'utils/config.ml' (this file not being existent any more after a 'make clean' in the OCaml sources). Camlp5 Version 6.01: -------------------- Camlp5 Version 6.00: -------------------- * [02 Sep 10] Added compatibility for OCaml versions 3.06, 3.05, 3.04, 3.03, 3.02, 3.01, 3.00, 2.99, 2.04, 2.03, 2.02, 2.01, 2.00 and 1.07 (but do not work on 64 bits architectures due to OCaml bug about input_value/output_value of that time: these versions can be used only on 32 bits architectures). Sometimes (but not always), some of the very old versions of OCaml (1.07, 2.00, 2.01) do not work, typically by raising Stack_overflow in the compiler or failing with segmentation faults in camlp5. * [28 Aug 10] Re-added module Ast2pt (file main/ast2pt.ml). Created file lib/versdep.ml and directory ocaml_src/lib/versdep for ocaml versions dependance. * [24 Aug 10] Added Makefile.withnew in directory etc for compilations that must be done with the new created camlp5. * [23 Aug 10] Changed variable 'NAME' into 'camlp5' in Makefiles and scripts. * [20 Aug 10] Added compatibility for OCaml version 3.07. * [18 Aug 10] Removed option "-qmod" (internal usage) from q_MLast.cmo. * [18 Aug 10] Changed sources to put '#load' instead of normalized comments. * [12 Aug 10] Added option "-ignloaddir" in "pa_r.ml". Camlp5 Version 5.14: --------------------- * [28 Apr 10] Fixed bug in "make boostrap_all_ast2pt". Camlp5 Version 5.13: --------------------- * [02 Nov 09] Moved all files ocaml_src/main/ast2pt.ml_ into new subdirectory ocaml_src/main/ast2p as ".ml". * [2009] Returned repository to CVS (was SVN). Camlp5 Version 5.08: --------------------- * [04 Jan 08] Converted "pr_extend.ml", "pr_extfun.ml" and "q_phony.ml" into usage of "pprintf". Camlp5 Version 5.07: --------------------- * [21 Dec 07] Changed all calls to "make" into "$(MAKE)" in Makefiles. (Some were missing.) Camlp5 Version 5.06: --------------------- Camlp5 Version 5.05: --------------------- * [28 Nov 07] Small change in interface Fstream for backtracking parsers. Camlp5 Version 5.04: --------------------- * [26 Nov 07] Added chapter titles in header of documentation in latex. * [22 Nov 07] Fixed small bug in "make install", displayed an error while testing the presence of cmx files. Camlp5 Version 5.03: --------------------- * [29 Oct 07] Replaced the exception [Grammar.SkipItem] (designed to make IFDEF in constructor declarations and pattern matching cases work) by the function [Grammar.skip_item]. Camlp5 Version 5.01: --------------------- * [06 Oct 2007] Added Prtools.vlistf, Prtools.plistf and Prtools.plistbf, same as their version without 'f', i.e. resp. Prtools.vlist, Prtools.plist and Prtools.plistb, but with the list being a list of functions returning a string allowing to use list of values of heterogen types. * [03 Oct 2007] Fixed bug in Prtools.plistb: if printing at least two elements, with the first one fitting in the line, a space was missing. E.g. using pr_r.cmo with "module M (N : P) (Q : R) = struct end". * [30 Sep 2007] Cleaned up and simplified q_MLast.ml pa_extend.ml pa_r.ml while keeping compatibility. Camlp5 Version 4.07: --------------------- * [30 Jul 2007] Removed type "Pcaml.err_ctx" and exception "Pcaml.Qerror" from the interface, since only used in the implementation. * [28 Jul 2007] Re-added option "-no_slist" of pr_extend.cmo which had disappeared after rewritting the pretty printing system. * [28 Jul 2007] Fixed name of symbol in case of use of FOLD0, FOLD0SEP, etc. and changed "simple_expr" in these syntax into 'expr LEVEL "simple"'. camlp5-rel8.00.02/LICENSE000066400000000000000000000030671410261051500145530ustar00rootroot00000000000000* Copyright (c) 2007-2017, INRIA (Institut National de Recherches en * Informatique et Automatique). All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of INRIA, nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY INRIA AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INRIA AND * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. camlp5-rel8.00.02/MODE000066400000000000000000000010051410261051500142030ustar00rootroot00000000000000In order to allow users to slowly convert to a new syntax tree, uncompatible with the previous one, Camlp5 can be compiled in two modes: - "transitional": syntax tree is compatible but the new syntax tree quotations kit in user syntax q_ast.cmo is not available. - "strict": the new syntax tree quotations kit in user syntax q_ast.cmo is available but the syntax tree is not compatible with the previous versions. You must choose among these modes at configuration time. See Camlp5 documentation. camlp5-rel8.00.02/Makefile000066400000000000000000000253141410261051500152050ustar00rootroot00000000000000# Makefile,v include config/Makefile DIRS=lib odyl main meta etc top ocpp man FDIRS=lib odyl main meta OPTDIRS=ocaml_stuff lib odyl main meta etc OPTOPTDIRS=compile SHELL=/bin/sh COLD_FILES=ocaml_src/main/argl.ml ocaml_src/main/mLast.mli ocaml_src/main/pcaml.ml ocaml_src/main/pcaml.mli ocaml_src/main/quotation.ml ocaml_src/main/quotation.mli ocaml_src/main/reloc.ml ocaml_src/main/reloc.mli ocaml_src/lib/extfun.ml ocaml_src/lib/extfun.mli ocaml_src/lib/fstream.ml ocaml_src/lib/fstream.mli ocaml_src/lib/gramext.ml ocaml_src/lib/gramext.mli ocaml_src/lib/grammar.ml ocaml_src/lib/grammar.mli ocaml_src/lib/plexer.ml ocaml_src/lib/plexer.mli ocaml_src/lib/stdpp.ml ocaml_src/lib/stdpp.mli ocaml_src/lib/token.ml ocaml_src/lib/token.mli ocaml_src/lib/versdep.ml ocaml_src/meta/pa_extend.ml ocaml_src/meta/pa_extend_m.ml ocaml_src/meta/pa_macro.ml ocaml_src/meta/pa_macro_gram.ml ocaml_src/meta/pa_r.ml ocaml_src/meta/pa_rp.ml ocaml_src/meta/pr_dump.ml ocaml_src/meta/q_MLast.ml ocaml_src/odyl/odyl_main.ml ocaml_src/odyl/odyl_main.mli ocaml_src/odyl/odyl.ml PR_O=pr_o.cmo DIFF_OPT=-Bwiu # For possible installation in a fake root directory # by "make install DESTDIR=..." DESTDIR= all: world.opt $(MAKE) $(MAKEFLAGS) local-install out: boot/$(CAMLP5N)$(EXE) set -e; cd ocaml_stuff; $(MAKE); cd .. set -e; for i in $(DIRS); do cd $$i; $(MAKE) all; cd ..; done opt: set -e; for i in $(OPTDIRS); do cd $$i; $(MAKE) opt; cd ..; done opt.opt: opt cd compile; $(MAKE) opt; cd .. ocaml_src/lib/versdep.ml: @echo "Please run 'configure' first"; exit 2 boot/$(CAMLP5N)$(EXE): $(COLD_FILES) set -e; cd ocaml_stuff; $(MAKE); cd .. $(MAKE) clean_cold $(MAKE) library_cold $(MAKE) compile_cold $(MAKE) promote_cold $(MAKE) clean_cold $(MAKE) clean_hot $(MAKE) library clean_hot: cd ocaml_stuff; $(MAKE) clean; cd .. for i in $(DIRS) compile; do (cd $$i; $(MAKE) clean; cd ..); done depend: cd etc; $(MAKE) pr_depend.cmo; cd .. cd ocaml_stuff; $(MAKE) depend; cd .. for i in $(DIRS) compile; do (cd $$i; $(MAKE) depend; cd ..); done local-install:: $(RM) -rf local-install && mkdir -p local-install/lib/ocaml $(MAKE) DESTDIR= LIBDIR=`pwd`/local-install/lib BINDIR=`pwd`/local-install/bin MANDIR=`pwd`/local-install/man install install: $(NOVERBOSE) if test -z "$(LIBDIR)"; then \ echo "*** Variable LIBDIR not set"; exit 1; fi $(NOVERBOSE) if test -z "$(CAMLP5N)"; then \ echo "*** Variable CAMLP5N not set"; exit 1; fi $(RM) -rf "$(DESTDIR)$(LIBDIR)/$(CAMLP5N)" for i in $(DIRS) compile; do \ (cd $$i; $(MAKE) install DESTDIR=$(DESTDIR) LIBDIR=$(LIBDIR) BINDIR=$(BINDIR) MANDIR=$(MANDIR); cd ..); \ done cp etc/topfind.camlp5 "$(DESTDIR)$(LIBDIR)/$(OCAMLN)/." || true uninstall: $(NOVERBOSE) if test -z "$(LIBDIR)"; then \ echo "*** Variable LIBDIR not set"; exit 1; fi $(NOVERBOSE) if test -z "$(CAMLP5N)"; then \ echo "*** Variable CAMLP5N not set"; exit 1; fi $(RM) -rf "$(DESTDIR)$(LIBDIR)/$(CAMLP5N)" cd "$(DESTDIR)$(BINDIR)"; $(RM) -f *$(CAMLP5N)* odyl ocpp; cd .. cd "$(DESTDIR)$(MANDIR)/man1"; $(RM) -f *$(CAMLP5N)* odyl ocpp $(RM) -f "$(DESTDIR)$(LIBDIR)/$(OCAMLN)"/topfind.camlp5 clean:: $(MAKE) clean_hot clean_cold $(RM) -f boot/*.cm[oi] boot/$(CAMLP5N)* $(RM) -rf boot/SAVED $(RM) -rf local-install $(MAKE) -C test clean $(MAKE) -C testsuite clean scratch: clean always: # Normal bootstrap bootstrap: $(MAKE) backup $(MAKE) promote $(MAKE) clean_hot $(MAKE) out $(MAKE) compare backup: mkdir boot.new $(MAKE) mv_git FROM=boot TO=boot.new mv boot boot.new/SAVED mv boot.new boot restore: mv boot/SAVED boot.new $(MAKE) mv_git FROM=boot TO=boot.new $(RM) -rf boot mv boot.new boot promote: for i in $(FDIRS); do (cd $$i; $(MAKE) promote; cd ..); done compare: $(NOVERBOSE) if (for i in $(FDIRS); do \ cd $$i; \ if $(MAKE) compare 2>/dev/null; then cd ..; \ else exit 1; fi; \ done); \ then echo "Fixpoint reached, bootstrap succeeded."; \ else echo "Fixpoint not reached, try one more bootstrapping cycle."; \ fi compare_test: $(NOVERBOSE) (for i in $(FDIRS); do \ cd $$i; \ if $(MAKE) compare 2>/dev/null; then cd ..; \ else exit 1; fi; \ done) cleanboot: $(RM) -rf boot/SAVED/SAVED # Core and core bootstrap coreboot: $(MAKE) backup $(MAKE) promote $(MAKE) clean_hot $(MAKE) core $(MAKE) compare core: boot/$(CAMLP5N)$(EXE) cd ocaml_stuff; $(MAKE) all; cd .. set -e; for i in $(FDIRS); do cd $$i; $(MAKE) all; cd ..; done clean_core: for i in $(FDIRS); do (cd $$i; $(MAKE) clean; cd ..); done # Everything in one command world: $(MAKE) core $(MAKE) compare_test || $(MAKE) coreboot $(MAKE) out world.opt: $(MAKE) core $(MAKE) compare_test || $(MAKE) coreboot $(MAKE) out $(MAKE) opt $(MAKE) opt.opt library: set -e; cd ocaml_stuff; $(MAKE); cd .. set -e; cd lib; $(MAKE) all; cd .. set -e; cd lib; $(MAKE) promote; cd .. # Cold start using pure Objective Caml sources library_cold: set -e; cd ocaml_src/lib; $(MAKE) all; cd ../.. set -e; cd ocaml_src/lib; $(MAKE) promote; cd ../.. compile_cold: cd ocaml_src; set -e; \ for i in $(FDIRS); do \ cd $$i; $(MAKE) all; cd ..; \ done; cd .. promote_cold: for i in $(FDIRS); do \ (cd ocaml_src/$$i; $(MAKE) promote; cd ../..); \ done clean_cold: for i in $(FDIRS); do \ (cd ocaml_src/$$i; $(MAKE) clean; cd ../..); \ done # Stealing some Ocaml compiler sources steal: cd ocaml_stuff; $(MAKE) steal; cd .. compare_stolen: cd ocaml_stuff; $(MAKE) compare_stolen; cd .. # Bootstrap the sources bootstrap_sources: $(RM) -rf ocaml_src.new mkdir ocaml_src.new $(MAKE) new_sources $(MAKE) untouch_sources $(MAKE) promote_sources $(MAKE) clean_sources bootstrap_source: $(RM) -rf ocaml_src.new mkdir -p ocaml_src.new/$$DIR $(MAKE) new_source DIR=$$DIR FILE=$$FILE mv ocaml_src.new/$$DIR/$$FILE ocaml_src/$$DIR/$$FILE rmdir ocaml_src.new/$$DIR rmdir ocaml_src.new new_sources: oprinter $(NOVERBOSE) for i in $(FDIRS); do \ mkdir ocaml_src.new/$$i; \ $(MAKE) $(NO_PR_DIR) new_source DIR=$$i FILE=Makefile; \ echo ============================================; \ echo ocaml_src.new/$$i/.depend; \ (cd ocaml_src.new/$$i; cp ../../$$i/.depend .); \ done $(NOVERBOSE) mkdir ocaml_src.new/lib/versdep $(NOVERBOSE) (cd ocaml_src/lib/versdep; \ cp *.ml ../../../ocaml_src.new/lib/versdep/.) $(NOVERBOSE) for i in $(FDIRS); do \ files="$$(cd $$i; ls *.ml*)"; \ for j in $$files; do \ if [ "$$j" != "odyl_config.ml" ]; then \ $(MAKE) $(NO_PR_DIR) new_source DIR=$$i FILE=$$j; \ fi; \ done; \ done new_source: $(NOVERBOSE) cd $$DIR; k=$$FILE; opt=""; \ if [ "$$k" = "versdep.ml" ]; then \ k=versdep$(VERSDIR)/$(OVERSION).ml; \ VERSDIR="$(OCAMLN)"; \ else \ VERSDIR=""; \ fi; \ if [ "$$k" = "odyl_main.ml" ]; then \ opt="$$opt -DBOOTSTRAPPING_SOURCES"; \ fi; \ echo ============================================; \ echo ocaml_src.new/$$DIR/$$k; \ if [ "$$k" = "Makefile" ]; then \ sed 's-^TOP=..$$-TOP=../..-' Makefile; \ else \ OCAMLN=$(OCAMLN) CAMLP5N=$(CAMLP5N) VERSDIR=$$VERSDIR \ ../tools/conv.sh $(PR_O) $$opt $$FILE; \ fi > \ ../ocaml_src.new/$$DIR/$$k compare_sources: oprinter $(NOVERBOSE) for i in $(FDIRS); do \ $(MAKE) $(NO_PR_DIR) compare_source DIR=$$i FILE=Makefile; \ echo ============================================; \ echo ocaml_src/$$i/.depend; \ (cd ocaml_src/$$i; diff $(DIFF_OPT) . ../../$$i/.depend); \ done $(NOVERBOSE) for i in $(FDIRS); do \ files="$$(cd $$i; ls *.ml*)"; \ for j in $$files; do \ if [ "$$j" != "odyl_config.ml" ]; then \ $(MAKE) $(NO_PR_DIR) compare_source DIR=$$i FILE=$$j; \ fi; \ done; \ done compare_source: $(NOVERBOSE) cd $$DIR; k=$$FILE; opt=""; \ if [ "$$k" = "versdep.ml" ]; then \ k=versdep$(VERSDIR)/$(OVERSION).ml; \ VERSDIR="$(OCAMLN)"; \ else \ VERSDIR=""; \ fi; \ if [ "$$k" = "odyl_main.ml" ]; then \ opt="$$opt -DBOOTSTRAPPING_SOURCES"; \ fi; \ echo ============================================; \ echo ocaml_src/$$DIR/$$k; \ if [ "$$k" = "Makefile" ]; then \ sed 's-^TOP=..$$-TOP=../..-' Makefile; \ else \ OCAMLN=$(OCAMLN) CAMLP5N=$(CAMLP5N) VERSDIR=$$VERSDIR \ ../tools/conv.sh $(PR_O) $$opt $$FILE; \ fi | \ diff $(DIFF_OPT) ../ocaml_src/$$DIR/$$k - || : bootstrap_all_versdep: oprinter $(NOVERBOSE) for i in ocaml_src/lib/versdep/*.ml; do \ $(MAKE) $(NO_PR_DIR) bootstrap_versdep i=$$i n=ocaml; \ done bootstrap_versdep: $(NOVERBOSE) cd lib; \ echo ============================================; \ echo $$i; \ j=$$(echo $$(basename $$i) | \ sed -e 's/^/OCAML_/;s/.ml//' -e 's/[.-]/_/g'); \ k=$$(echo OCAML_$(OVERSION) | sed -e 's/[.-]/_/g'); \ m=$$(echo $(OCAMLN) | tr a-z A-Z); \ n=$$(echo $$n | tr a-z A-Z); \ opt="-U$$k -U$$m -D$$j -D$$n"; \ OCAMLN=$(OCAMLN) CAMLP5N=$(CAMLP5N) ../tools/conv.sh $(PR_O) $$opt \ versdep.ml > ../$$i compare_all_versdep: oprinter $(NOVERBOSE) for i in ocaml_src/lib/versdep/*.ml; do \ $(MAKE) $(NO_PR_DIR) compare_versdep i=$$i n=ocaml; \ done; \ for i in ocaml_src/lib/versdep/*/*.ml; do \ n="$$(basename $$(dirname $$i))"; \ $(MAKE) $(NO_PR_DIR) compare_versdep i=$$i n=$$n; \ done compare_versdep: $(NOVERBOSE) cd lib; \ echo ============================================; \ echo $$i; \ j=$$(echo $$(basename $$i) | \ sed -e 's/^/OCAML_/;s/.ml//' -e 's/[.-]/_/g'); \ k=$$(echo OCAML_$(OVERSION) | sed -e 's/[.-]/_/g'); \ m=$$(echo $(OCAMLN) | tr a-z A-Z); \ n=$$(echo $$n | tr a-z A-Z); \ opt="-U$$k -U$$m -D$$j -D$$n"; \ OCAMLN=$(OCAMLN) CAMLP5N=$(CAMLP5N) \ ../tools/conv.sh $(PR_O) $$opt versdep.ml | \ diff $(DIFF_OPT) ../$$i - oprinter: cd etc; $(MAKE) $(PR_O) untouch_sources: $(NOVERBOSE) cd ocaml_src; \ for i in $(FDIRS) lib/versdep; do \ for j in $$i/*.ml* $$i/Makefile*; do \ if cmp -s $$j ../ocaml_src.new/$$j 2>/dev/null; then \ cp -p $$j ../ocaml_src.new/$$j; \ fi; \ done; \ done promote_sources: $(MAKE) mv_git FROM=ocaml_src TO=ocaml_src.new for i in $(FDIRS) lib/versdep; do \ $(MAKE) mv_git FROM=ocaml_src/$$i TO=ocaml_src.new/$$i; \ done mv ocaml_src/tools ocaml_src.new/. mv ocaml_src ocaml_src.new/SAVED mv ocaml_src.new ocaml_src unpromote_sources: mv ocaml_src ocaml_src.new mv ocaml_src.new/SAVED ocaml_src mv ocaml_src.new/tools ocaml_src/. for i in $(FDIRS) lib/versdep; do \ $(MAKE) mv_git FROM=ocaml_src.new/$$i TO=ocaml_src/$$i; \ done $(MAKE) mv_git FROM=ocaml_src.new TO=ocaml_src clean_sources: $(RM) -rf ocaml_src/SAVED/SAVED printer: cd etc; $(MAKE) $(PR_O) # Utility mv_cvs: test ! -d $(FROM)/CVS || mv $(FROM)/CVS $(TO)/. test ! -f $(FROM)/.cvsignore || mv $(FROM)/.cvsignore $(TO)/. mv_svn: test ! -d $(FROM)/.svn || mv $(FROM)/.svn $(TO)/. test ! -f $(FROM)/.cvsignore || mv $(FROM)/.cvsignore $(TO)/. mv_git: test ! -f $(FROM)/.gitignore || mv $(FROM)/.gitignore $(TO)/. .PHONY: install camlp5-rel8.00.02/README.md000066400000000000000000000070271410261051500150250ustar00rootroot00000000000000# Camlp5 Camlp5 is a preprocessor-pretty-printer of OCaml. It is compatible with all versions of OCaml from 4.00.0 thru 4.11.0. Previous versions of Camlp5 have supported OCaml versions down to 1.07 and jocaml 3.12.0 to 3.12.1, but this version cuts off support at 4.00.0. Camlp5 is heavily tested with OCaml versions from 4.10.0 forward, with an extensive and ever-growing testsuite. This Camlp5 version is 8.00.02. NOTE WELL that this is an **new** release (very different from the 7.xx releases), and as such, may break your code. If it does, please do reach out to me, and I'll be happy to help upgrade it. I'm still working on the documentation, but .... that could take a while, so I figured I had better get this out and find out where code breaks, so I can fix that. ## Documentation: Installation, Testsuite, Tutorial Since most OCaml users will install Camlp5 via opam, all the documentation has been moved over to Sphinx/RST, and is available in `doc/rst/_build` as well as [on ReadTheDocs](https://camlp5.readthedocs.io/en/latest/). - Introduction: `doc/rst/_build/intro.html`, [on ReadTheDocs](https://camlp5.readthedocs.io/en/latest/intro.html). This introduction explains how to use Camlp5 from the commandline and toplevel: compiling files, loading into toplevel, selecting syntax (original or revised). I'd recommend starting here before trying one of the tutorials. - Building, Requirements & Installation: `doc/rst/_build/building.html`, [on ReadTheDocs](https://camlp5.readthedocs.io/en/latest/building.html). This covers building Camlp5 "manually", as well as building the documentation, testsuite, and tutorial examples. - Tutorials (using Camlp5): `doc/rst/_build/tutorial-language-processing.html`, [on ReadTheDocs](https://camlp5.readthedocs.io/en/latest/tutorial-language-processing.html). This covers how to use Camlp5 to write new language processors (the running example of a calculator with parsing, pretty-printing, and evaluation), using Camlp5 infrastructure, as well as interfacing with Ocamllex. - Tutorials (extending OCaml Syntax): `doc/rst/_build/tutorial-extending-camlp5.html`, [on ReadTheDocs](https://camlp5.readthedocs.io/en/latest/tutorial-extending-camlp5.html). This covers how to use Camlp5 to write new syntax-extensions for Ocaml, using the example new syntax ``sum 1 ; 2 end``. Some tutorials are provided in both original and revised syntax: eventually all will be provided in both forms. ### Outdated HTML Documentation The directory doc/htmlp contains the sources of outdated HTML documentation. It will be removed once the Sphinx documentation is fully updated. To build it, cd doc/htmlp, and: * for its html version, type "make", result in directory ../html * for its latex version, type "make tex", result camlp5.tex * for its ps version x-rtype "make ps", result camlp5.ps * for its pdf version, type "make pdf", result camlp5.pdf * for its info version, type "make info", result camlp5.info* ## Problems If you have problems compiling your source files with this version of Camlp5, please contact me (Chet Murthy ) and I'll help you resolve them. I can't promise, but it's likely I can just fork your repo, fix the problem, and send you a PR. For really old code, the reason can be that there the new type 'location' is now abstract. Consider looking at the file UPGRADING. ## Author(s) Originally written by Daniel de Rauglaudre . Maintenance and upgrades by Chet Murthy . All bugs are my (Chet's) fault, all good ideas are Daniel's. camlp5-rel8.00.02/RELEASING000066400000000000000000000025461410261051500150030ustar00rootroot00000000000000HOW TO MAKE A RELEASE (WHEN YOU ARE ADMINISTRATOR). 1. Edit main/pcaml.ml and change version name. In general, it suffices to remove "-exp" (changing e.g. "7.09-exp" by just "7.09"). 2. Do the same thing in file ocaml_src/main/pcaml.ml (cold source). 3. Edit file README.md, also update version number. 4. Commit and push in github. 5. Do a tag by typing "git tag relv" where "v" is the release number with only the digits (e.g. 709 if release is 7.09, resulting rel709). 6. Push tags by taping "git push --tags". 7. Check if present in github camlp5/camlp5 "release". Then go to cloned directory camlp5.github.io and 1. Copy CHANGES from camlp5 into CHANGES.txt 2. Copy README.md from camlp5. 3. Edit file index.html, change the version number, the release date and the tar.gz link and name. 4. VERIFY that the opam file does not contain a "uninstall" stanza, and that the version number in the filename is NN.MM, viz. "camlp5.7.12". 5. Commit and push. After some minutes, the home dir of camlp5 https://camlp5.github.io/ should be updated AFTER THE RELEASE 1. Edit files main/pcaml.ml, ocaml_src/main/pcaml.ml and README.md to reflect new preparing version, changing, e.g. "7.09" into "7.10-exp" in these three files. 2. Edit CHANGES to add new title for new version, e.g. Camlp5 Version 7.10: -------------------- 3. Commit and push. camlp5-rel8.00.02/UPGRADING000066400000000000000000000026311410261051500150050ustar00rootroot00000000000000Since version 4.0 Once this version of Camlp5 installed, if your files do not compile, it be due to the new type 'location' which is now abstract. In particular, you can see it as first parameter of the exception 'Exc_located' (now renamed 'Ploc.Exc' but name compatibility is assumed) raised by the function 'Stdpp.raise_with_loc' (now renamed 'Ploc.raise'). If you handled that exception and looked at the 'location' by considering it is a couple of source positions ('int' or 'Lexing.position' depending on the version of Camlp4 you had before), it does not work any more. Look at the functions defined in 'ploc.mli'. To get the first and last positions of a location, use the functions 'Ploc.first_pos' and 'Ploc.last_pos'. They return integers, which are positions in characters from the beginning of the file. But you can also get the line number by the function 'Ploc.line_nb'. Consider also using the function 'Ploc.encl'. See the other functions. With Camlp5, when loading 'pa_macro.cmo', you get the identifier 'CAMLP5' defined. If you want to make your sources compatible with several versions of Camlp4 or Camlp5, you can add, in , , or toplevel definition (), things like : IFDEF CAMLP5 THEN ELSE END camlp5-rel8.00.02/boot/000077500000000000000000000000001410261051500145035ustar00rootroot00000000000000camlp5-rel8.00.02/boot/.gitignore000066400000000000000000000000471410261051500164740ustar00rootroot00000000000000*.cm[oia] camlp5 camlp5o camlp5r SAVED camlp5-rel8.00.02/compile/000077500000000000000000000000001410261051500151705ustar00rootroot00000000000000camlp5-rel8.00.02/compile/.depend000066400000000000000000000004001410261051500164220ustar00rootroot00000000000000compile.cmo: ../lib/gramext.cmi ../lib/grammar.cmi ../lib/ploc.cmi \ ../lib/versdep.cmo ../main/mLast.cmi ../main/pcaml.cmi compile.cmx: ../lib/gramext.cmx ../lib/grammar.cmx ../lib/ploc.cmx \ ../lib/versdep.cmx ../main/mLast.cmi ../main/pcaml.cmx camlp5-rel8.00.02/compile/.gitignore000066400000000000000000000001441410261051500171570ustar00rootroot00000000000000*.cm[oix] *.fast *.fast.opt o_fast.ml.tmp r_fast.ml.tmp pa_o_fast.ml pa_r_fast.ml *.ppo tmp.* *.tmp camlp5-rel8.00.02/compile/Makefile000066400000000000000000000037571410261051500166440ustar00rootroot00000000000000# Makefile,v TOP=.. include ../config/Makefile INCLUDES=-I ../main -I ../boot -I ../lib OCAMLCFLAGS=$(DEBUG) $(OCAMLC_W_Y) $(WARNERR) $(INCLUDES) D=o SRC=../etc/pa_$(D).ml ../etc/pa_$(D)p.ml COMP_OPT=-strict_parsing COMP_OPT=-e "Grammar.Entry.obj Pcaml.interf" \ -e "Grammar.Entry.obj Pcaml.implem" \ -e "Grammar.Entry.obj Pcaml.top_phrase" \ -e "Grammar.Entry.obj Pcaml.use_file" \ RM=rm all: out out: $(CAMLP5N)$D.fast opt: $(CAMLP5N)$D.fast.opt $(CAMLP5N)$D.fast: pa_$D_fast.cmo $(RM) -f $(CAMLP5N)$D.fast cd ../main; $(MAKE) CAMLP5=../compile/$(CAMLP5N)$D.fast CAMLP5M="../compile/pa_$D_fast.cmo ../meta/pr_dump.cmo" $(CAMLP5N)$D.fast.opt: pa_$D_fast.cmx $(RM) -f $(CAMLP5N)$D.fast.opt cd ../main; $(MAKE) optp5 CAMLP5OPT=../compile/$(CAMLP5N)$D.fast.opt CAMLP5M="../compile/pa_$D_fast.cmx ../meta/pr_dump.cmx" pa_$D_fast.ml: compile.cmo comp_head.ml.tpl comp_trail.ml.tpl $(SRC) cat $(SRC) | perl -n -e 'print unless /#load/' > tmp.$D_concat.ml ../meta/camlp5r -I ../meta -I ../etc pa_extend.cmo q_MLast.cmo pa_macro.cmo pa_macro_gram.cmo pr_r.cmo pr_ro.cmo pr_extend.cmo tmp.$D_concat.ml > tmp.$D_postprocessed.ml.ppo.TMP && mv tmp.$D_postprocessed.ml.ppo.TMP tmp.$D_postprocessed.ml.ppo ./strip-parser.pl tmp.$D_postprocessed.ml.ppo > $D_stripped.tmp OCAMLN=$(OCAMLN) CAMLP5N=$(CAMLP5N) EXE=$(EXE) RM=$(RM) ./compile.sh $(COMP_OPT) $(SRC) > $D_fast.ml.tmp cat comp_head.ml.tpl $D_stripped.tmp $D_fast.ml.tmp comp_trail.ml.tpl > pa_$D_fast.ml install: if test -f $(CAMLP5N)o.fast.opt; then \ cp $(CAMLP5N)o.fast.opt "$(DESTDIR)$(BINDIR)/$(CAMLP5N)o.opt"; \ fi if test -f pa_o_fast.cmx; then \ cp pa_o_fast.cmx pa_o_fast.o "$(DESTDIR)$(LIBDIR)/$(CAMLP5N)/."; \ fi clean:: $(RM) -f *.cm* *.pp[io] *.[oa] *.lib *.obj *.bak .*.bak *.out *.opt $(RM) -f *.fast tmp.* pa_*_fast.ml *.tmp *.ppo depend: cp .depend .depend.bak > .depend @export LC_ALL=C; for i in *.ml; do \ ../tools/depend.sh $(INCLUDES) -name $(CAMLP5N) $$i \ >> .depend; \ done include .depend camlp5-rel8.00.02/compile/comp_head.ml.tpl000066400000000000000000000043551410261051500202460ustar00rootroot00000000000000(* camlp5r *) (* comp_head.ml.tpl,v *) (* Copyright (c) INRIA 2007-2017 *) #load "q_MLast.cmo"; #load "pa_extend.cmo"; module P = struct value gloc bp strm = Grammar.loc_of_token_interval bp (Stream.count strm); value vala symb = parser [: a = symb :] -> <:vala< a >>; value list0 symb = let rec loop al = parser [ [: a = symb; a = loop [a :: al] ! :] -> a | [: :] -> al ] in parser [: a = loop [] :] -> List.rev a ; value list0sep symb sep b = if not b then let rec kont al = parser [ [: v = sep; a = symb; a = kont [a :: al] ! :] -> a | [: :] -> al ] in parser [ [: a = symb; a = kont [a] ! :] -> List.rev a | [: :] -> [] ] else failwith "LIST0 _ SEP _ OPT_SEP not yet implemented" ; value list1 symb = let rec loop al = parser [ [: a = symb; a = loop [a :: al] ! :] -> a | [: :] -> al ] in parser [: a = symb; a = loop [a] ! :] -> List.rev a ; value list1sep symb sep b = if not b then let rec kont al = parser [ [: v = sep; a = symb; a = kont [a :: al] ! :] -> a | [: :] -> al ] in parser [: a = symb; a = kont [a] ! :] -> List.rev a else let rec kont al = parser [ [: v = sep; a = symb; a = kont [a :: al] ! :] -> a | [: v = sep :] -> al | [: :] -> al ] in parser [: a = symb; a = kont [a] ! :] -> List.rev a ; value option f = parser [ [: a = f :] -> Some a | [: :] -> None ] ; value bool f = parser [ [: _ = f :] -> True | [: :] -> False ] ; value token (p_con, p_prm) = if p_prm = "" then parser [: `(con, prm) when con = p_con :] -> prm else parser [: `(con, prm) when con = p_con && prm = p_prm :] -> prm ; value orzero f f0 = parser [ [: a = f :] -> a | [: a = f0 :] -> a ] ; value error entry prev_symb symb = symb ^ " expected" ^ (if prev_symb = "" then "" else " after " ^ prev_symb) ^ " (in [" ^ entry ^ "])" ; value lexer = lazy (Plexer.gmake ()); end ; (****************************************) camlp5-rel8.00.02/compile/comp_trail.ml.tpl000066400000000000000000000010631410261051500204510ustar00rootroot00000000000000 (****************************************) value interf_p = Grammar.Entry.of_parser Pcaml.gram "interf" interf_0 ; value implem_p = Grammar.Entry.of_parser Pcaml.gram "implem" implem_0 ; value top_phrase_p = Grammar.Entry.of_parser Pcaml.gram "top_phrase" top_phrase_0 ; value use_file_p = Grammar.Entry.of_parser Pcaml.gram "use_file" use_file_0 ; EXTEND interf: [ [ x = interf_p -> x ] ] ; implem: [ [ x = implem_p -> x ] ] ; top_phrase: [ [ x = top_phrase_p -> x ] ] ; use_file: [ [ x = use_file_p -> x ] ] ; END; camlp5-rel8.00.02/compile/compile.ml000066400000000000000000000470331410261051500171610ustar00rootroot00000000000000(* camlp5r *) (* compile.ml,v *) (* Copyright (c) INRIA 2007-2017 *) #load "q_MLast.cmo"; #load "pa_macro.cmo"; open Gramext; open Versdep; value strict_parsing = ref False; value keywords = ref []; value loc = Ploc.dummy; (* Watch the segmentation faults here! the compiled file must have been loaded in camlp5 with the option pa_extend.cmo -meta_action. *) value magic_act (act : Obj.t) : MLast.expr = Obj.magic act; (* Names of symbols for error messages; code borrowed to grammar.ml *) value rec name_of_symbol entry = fun [ Snterm e -> "[" ^ e.ename ^ "]" | Snterml e l -> "[" ^ e.ename ^ " level " ^ l ^ "]" | Sself | Snext -> "[" ^ entry.ename ^ "]" | Stoken tok -> entry.egram.glexer.Plexing.tok_text tok | Svala _ s -> name_of_symbol entry s | _ -> "???" ] ; value rec name_of_symbol_failed entry = fun [ Slist0 s -> name_of_symbol_failed entry s | Slist0sep s _ _ -> name_of_symbol_failed entry s | Slist1 s -> name_of_symbol_failed entry s | Slist1sep s _ _ -> name_of_symbol_failed entry s | Sopt s -> name_of_symbol_failed entry s | Sflag s -> name_of_symbol_failed entry s | Stree t -> name_of_tree_failed entry t | s -> name_of_symbol entry s ] and name_of_tree_failed entry = fun [ Node {node = s; brother = bro; son = son} -> let txt = name_of_symbol_failed entry s in let txt = match (s, son) with [ (Sopt _ | Sflag _, Node _) -> txt ^ " or " ^ name_of_tree_failed entry son | _ -> txt ] in let txt = match bro with [ DeadEnd | LocAct _ _ -> txt | _ -> txt ^ " or " ^ name_of_tree_failed entry bro ] in txt | DeadEnd | LocAct _ _ -> "???" ] ; value tree_failed entry prev_symb tree = let (s2, s3) = let txt = name_of_tree_failed entry tree in match prev_symb with [ Slist0 s -> let txt1 = name_of_symbol_failed entry s in ("", txt1 ^ " or " ^ txt) | Slist1 s -> let txt1 = name_of_symbol_failed entry s in ("", txt1 ^ " or " ^ txt) | Slist0sep s sep _ -> let txt1 = name_of_symbol_failed entry s in ("", txt1 ^ " or " ^ txt) | Slist1sep s sep _ -> let txt1 = name_of_symbol_failed entry s in ("", txt1 ^ " or " ^ txt) | Sopt _ | Sflag _ | Stree _ -> ("", txt) | _ -> (name_of_symbol entry prev_symb, txt) ] in <:expr< P.error $str:entry.ename$ $str:String.escaped s2$ $str:String.escaped s3$ >> ; (* Compilation *) value rec find_act = fun [ DeadEnd -> failwith "find_act" | LocAct (_, act) _ -> (magic_act act, 0) | Node {son = son; brother = bro} -> let (act, n) = try find_act son with [ Failure _ -> find_act bro ] in (act, n + 1) ] ; value level_number e l = match e.edesc with [ Dlevels elevs -> loop 0 elevs where rec loop n = fun [ [lev :: levs] -> if lev.lname = Some l then n else loop (n + 1) levs | [] -> failwith ("level " ^ l ^ " not found in entry " ^ e.ename) ] | Dparser _ -> 0 ] ; value nth_patt_of_act (e, n) = let patt_list = loop e where rec loop = fun [ <:expr< fun (loc : Ploc.t) -> $_$ >> -> [] | <:expr< fun ($p$ : $_$) -> $e$ >> -> [p :: loop e] | <:expr< fun $p$ -> $e$ >> -> [p :: loop e] | _ -> failwith "nth_patt_of_act" ] in List.nth patt_list n ; value rec last_patt_of_act = fun [ <:expr< fun ($p$ : $_$) (loc : Ploc.t) -> $_$ >> -> p | <:expr< fun $_$ -> $e$ >> -> last_patt_of_act e | _ -> failwith "last_patt_of_act" ] ; value rec final_action = fun [ <:expr< fun (loc : Ploc.t) -> ($e$ : $_$) >> -> e | <:expr< fun $_$ -> $e$ >> -> final_action e | _ -> failwith "final_action" ] ; value parse_standard_symbol e rkont fkont ending_act = <:expr< match try Some ($e$ strm__) with [ Stream.Failure -> None ] with [ Some $nth_patt_of_act ending_act$ -> $rkont$ | _ -> $fkont$ ] >> ; value parse_symbol_no_failure e rkont fkont ending_act = <:expr< let $nth_patt_of_act ending_act$ = try $e$ strm__ with [ Stream.Failure -> raise (Stream.Error "") ] in $rkont$ >> ; value rec contain_loc = fun [ <:expr< $lid:s$ >> -> s = "loc" | <:expr< $uid:_$ >> -> False | <:expr< $str:_$ >> -> False | <:expr< ($list:el$) >> -> List.exists contain_loc el | <:expr< $e1$ $e2$ >> -> contain_loc e1 || contain_loc e2 | _ -> True ] ; value gen_let_loc loc e = if contain_loc e then <:expr< let loc = P.gloc bp strm__ in $e$ >> else e ; value phony_entry = Grammar.Entry.obj Pcaml.implem; value rec get_token_list entry tokl last_tok tree = match tree with [ Node {node = Stoken tok; son = son; brother = DeadEnd} -> get_token_list entry [last_tok :: tokl] (tok, None) son | Node {node = Svala ls (Stoken tok); son = son; brother = DeadEnd} -> get_token_list entry [last_tok :: tokl] (tok, Some ls) son | _ -> if tokl = [] then None else Some (List.rev [last_tok :: tokl], last_tok, tree) ] ; value patt_of_token patt tok = let _ = if fst tok = "" && not (List.mem (snd tok) keywords.val) then keywords.val := [snd tok :: keywords.val] else () in let p_con = String.escaped (fst tok) in let p_prm = String.escaped (snd tok) in if snd tok = "" then if fst tok = "ANY" then <:patt< (_, $patt$) >> else <:patt< ($str:p_con$, $patt$) >> else match patt with [ <:patt< _ >> -> <:patt< ($str:p_con$, $str:p_prm$) >> | _ -> <:patt< ($str:p_con$, ($str:p_prm$ as $patt$)) >> ] ; value rec parse_tree entry nlevn alevn (tree, fst_symb) act_kont kont = match tree with [ DeadEnd -> kont | LocAct (_, act) _ -> let act = magic_act act in act_kont False act | Node {node = Sself; son = LocAct (_, act) _; brother = bro} -> let act = magic_act act in let n = entry.ename ^ "_" ^ string_of_int alevn in let e = if strict_parsing.val || alevn = 0 || fst_symb then <:expr< $lid:n$ >> else <:expr< P.orzero $lid:n$ $lid:entry.ename ^ "_0"$ >> in let p2 = match bro with [ DeadEnd -> kont | _ -> parse_tree entry nlevn alevn (bro, fst_symb) act_kont kont ] in let p1 = act_kont True act in parse_standard_symbol e p1 p2 (act, 0) | Node {node = s; son = LocAct (_, act) _; brother = bro} -> let act = magic_act act in let p2 = parse_tree entry nlevn alevn (bro, fst_symb) act_kont kont in let p1 = act_kont False act in parse_symbol entry nlevn s p1 p2 (act, 0) | Node {node = s; son = son; brother = bro} -> let tokl = match s with [ Stoken tok -> get_token_list entry [] (tok, None) son | Svala ls (Stoken tok) -> get_token_list entry [] (tok, Some ls) son | _ -> None ] in let p2 = parse_tree entry nlevn alevn (bro, fst_symb) act_kont kont in match tokl with [ Some (([_; _ :: _] as tokl), last_tok, son) -> let len = List.length tokl in let (act, n) = find_act son in let (p, _) = List.fold_right (fun (tok, vala) (pl, n) -> let patt = nth_patt_of_act (act, n) in let p = patt_of_token patt tok in (<:patt< [$p$ :: $pl$] >>, n + 1)) tokl (<:patt< [] >>, n) in let p1 = parse_kont entry nlevn alevn act_kont s son in let p1 = if not Pcaml.strict_mode.val then p1 else let (e, _) = List.fold_right (fun (tok, vala) (e, n) -> let e = let p = nth_patt_of_act (act, n) in match p with [ <:patt< $lid:x$ >> -> let x = <:expr< $lid:x$ >> in match vala with [ Some al -> <:expr< let $p$ = Ploc.VaVal $x$ in $e$ >> | None -> e ] | _ -> e ] in (e, n + 1)) tokl (p1, n) in e in let el = List.fold_left (fun el _ -> [<:expr< Stream.junk strm__ >> :: el]) [p1] tokl in <:expr< match Stream.npeek $int:string_of_int len$ strm__ with [ $p$ -> do { $list:el $ } | _ -> $p2$ ] >> | _ -> let p1 = parse_kont entry nlevn alevn act_kont s son in parse_symbol entry nlevn s p1 p2 (find_act son) ] ] and parse_kont entry nlevn alevn act_kont s son = let err = let txt = tree_failed entry s son in <:expr< raise (Stream.Error $txt$) >> in match son with [ Node {brother = DeadEnd} -> parse_tree entry nlevn alevn (son, False) act_kont err | _ -> let p1 = parse_tree entry nlevn alevn (son, True) act_kont <:expr< raise Stream.Failure >> in <:expr< try $p1$ with [ Stream.Failure -> $err$ ] >> ] and parse_symbol entry nlevn s rkont fkont ending_act = match s with [ Stoken tok -> let patt = nth_patt_of_act ending_act in let p = patt_of_token patt tok in <:expr< match Stream.peek strm__ with [ Some $p$ -> do { Stream.junk strm__; $rkont$ } | _ -> $fkont$ ] >> | s -> let e = symbol_parser entry nlevn s in match s with [ Slist0 _ | Slist0sep _ _ _ | Sopt _ | Sflag _ -> parse_symbol_no_failure e rkont fkont ending_act | s -> parse_standard_symbol e rkont fkont ending_act ] ] and symbol_parser entry nlevn = fun [ Slist0 s -> <:expr< P.list0 $symbol_parser entry nlevn s$ >> | Slist1 s -> <:expr< P.list1 $symbol_parser entry nlevn s$ >> | Slist0sep s sep b -> let b = if b then <:expr< True >> else <:expr< False >> in <:expr< P.list0sep $symbol_parser entry nlevn s$ $symbol_parser entry nlevn sep$ $b$ >> | Slist1sep s sep b -> let b = if b then <:expr< True >> else <:expr< False >> in <:expr< P.list1sep $symbol_parser entry nlevn s$ $symbol_parser entry nlevn sep$ $b$ >> | Sopt s -> <:expr< P.option $symbol_parser entry nlevn s$ >> | Sflag s -> <:expr< P.bool $symbol_parser entry nlevn s$ >> | Stree tree -> let kont = <:expr< raise Stream.Failure >> in let act_kont _ act = gen_let_loc loc (final_action act) in let e = parse_tree phony_entry 0 0 (tree, True) act_kont kont in <:expr< fun (strm__ : Stream.t _) -> $e$ >> | Snterm e -> let n = match e.edesc with [ Dparser _ -> e.ename | Dlevels _ -> e.ename ^ "_0" ] in <:expr< $lid:n$ >> | Snterml e l -> let n = e.ename ^ "_" ^ string_of_int (level_number e l) in <:expr< $lid:n$ >> | Sself -> let n = entry.ename ^ "_0" in <:expr< $lid:n$ >> | Snext -> let n = entry.ename ^ "_" ^ string_of_int nlevn in if strict_parsing.val then <:expr< $lid:n$ >> else let n0 = entry.ename ^ "_0" in <:expr< P.orzero $lid:n$ $lid:n0$ >> | Stoken tok -> let _ = if fst tok = "" && not (List.mem (snd tok) keywords.val) then keywords.val := [snd tok :: keywords.val] else () in let p_con = String.escaped (fst tok) in let p_prm = String.escaped (snd tok) in <:expr< P.token ($str:p_con$, $str:p_prm$) >> | Svala _ s -> <:expr< P.vala $symbol_parser entry nlevn s$ >> | _ -> <:expr< aaa >> ] ; value rec start_parser_of_levels entry clevn levs = let n = entry.ename ^ "_" ^ string_of_int clevn in let next = entry.ename ^ "_" ^ string_of_int (clevn + 1) in let p = <:patt< $lid:n$ >> in match levs with [ [] -> [Some (p, <:expr< fun (strm__ : Stream.t _) -> raise Stream.Failure >>)] | [lev :: levs] -> let pel = start_parser_of_levels entry (succ clevn) levs in match lev.lprefix with [ DeadEnd -> let ncont = if not strict_parsing.val && clevn = 0 then entry.ename ^ "_gen_cont" else entry.ename ^ "_" ^ string_of_int clevn ^ "_cont" in let curr = <:expr< let a = $lid:next$ strm__ in $lid:ncont$ bp a strm__ >> in let curr = <:expr< let bp = Stream.count strm__ in $curr$ >> in let e = <:expr< fun (strm__ : Stream.t _) -> $curr$ >> in let pel = if levs = [] then [] else pel in [Some (p, e) :: pel] | tree -> let alevn = clevn in let (kont, pel) = match levs with [ [] -> (<:expr< raise Stream.Failure >>, []) | _ -> let e = match (lev.assoc, lev.lsuffix) with [ (NonA, _) | (_, DeadEnd) -> <:expr< $lid:next$ strm__ >> | _ -> let ncont = entry.ename ^ "_" ^ string_of_int clevn ^ "_cont" in <:expr< let a = $lid:next$ strm__ in $lid:ncont$ bp a strm__ >> ] in (e, pel) ] in let act_kont end_with_self act = if lev.lsuffix = DeadEnd then gen_let_loc loc (final_action act) else let ncont = entry.ename ^ "_" ^ string_of_int clevn ^ "_cont" in gen_let_loc loc <:expr< $lid:ncont$ bp $final_action act$ strm__ >> in let curr = parse_tree entry (succ clevn) alevn (tree, True) act_kont kont in let curr = <:expr< let bp = Stream.count strm__ in $curr$ >> in let e = <:expr< fun (strm__ : Stream.t _) -> $curr$ >> in [Some (p, e) :: pel] ] ] ; value rec continue_parser_of_levels entry clevn levs = let n = entry.ename ^ "_" ^ string_of_int clevn ^ "_cont" in let p = <:patt< $lid:n$ >> in match levs with [ [] -> [None] | [lev :: levs] -> let pel = continue_parser_of_levels entry (succ clevn) levs in match lev.lsuffix with [ DeadEnd -> [None :: pel] | tree -> let alevn = match lev.assoc with [ LeftA | NonA -> succ clevn | RightA -> clevn ] in let (kont, pel) = match levs with [ [] -> (<:expr< a__ >>, []) | _ -> (<:expr< a__ >>, pel) ] in let act_kont end_with_self act = let p = last_patt_of_act act in match lev.assoc with [ RightA | NonA -> <:expr< let $p$ = a__ in $gen_let_loc loc (final_action act)$ >> | LeftA -> let ncont = entry.ename ^ "_" ^ string_of_int clevn ^ "_cont" in gen_let_loc loc <:expr< let $p$ = a__ in $lid:ncont$ bp $final_action act$ strm__ >> ] in let curr = parse_tree entry (succ clevn) alevn (tree, True) act_kont kont in let e = <:expr< fun bp a__ strm__ -> $curr$ >> in [Some (p, e) :: pel] ] ] ; value continue_parser_of_levels_again entry levs = let n = entry.ename ^ "_gen_cont" in let e = loop <:expr< a__ >> 0 levs where rec loop var levn = fun [ [] -> <:expr< if x == a__ then x else $lid:n$ bp x strm__ >> | [lev :: levs] -> match lev.lsuffix with [ DeadEnd -> loop var (levn + 1) levs | _ -> let n = entry.ename ^ "_" ^ string_of_int levn ^ "_cont" in let rest = loop <:expr< x >> (levn + 1) levs in <:expr< let x = $lid:n$ bp $var$ strm__ in $rest$ >> ] ] in (<:patt< $lid:n$ >>, <:expr< fun bp a__ strm__ -> $e$ >>) ; value empty_entry ename = let p = <:patt< $lid:ename$ >> in let e = <:expr< fun (strm__ : Stream.t _) -> raise (Stream.Error $str:"entry [" ^ ename ^ "] is empty"$) >> in [Some (p, e)] ; value start_parser_of_entry entry = match entry.edesc with [ Dlevels [] -> empty_entry entry.ename | Dlevels elev -> start_parser_of_levels entry 0 elev | Dparser p -> [] ] ; value continue_parser_of_entry entry = match entry.edesc with [ Dlevels elev -> continue_parser_of_levels entry 0 elev | Dparser p -> [] ] ; value continue_parser_of_entry_again entry = if strict_parsing.val then [] else match entry.edesc with [ Dlevels ([_; _ :: _] as levs) -> [continue_parser_of_levels_again entry levs] | _ -> [] ] ; value rec list_alternate l1 l2 = match (l1, l2) with [ ([x1 :: l1], [x2 :: l2]) -> [x1; x2 :: list_alternate l1 l2] | ([], l2) -> l2 | (l1, []) -> l1 ] ; value compile_entry entry = let pel1 = start_parser_of_entry entry in let pel2 = continue_parser_of_entry entry in let pel = list_alternate pel1 pel2 in let pel = List.fold_right (fun pe list -> match pe with [ Some pe -> [pe :: list] | None -> list ]) pel (continue_parser_of_entry_again entry) in List.map (fun (p,e) -> (p,e,<:vala< [] >>)) pel ; (* get all entries connected together *) (* should be rewritten using a derived version of 'Grammar.iter_entry' *) value rec scan_tree list = fun [ Node {node = n; son = son; brother = bro} -> let list = scan_symbol list n in let list = scan_tree list son in let list = scan_tree list bro in list | LocAct _ _ | DeadEnd -> list ] and scan_symbol list = fun [ Sfacto e -> scan_symbol list e | Snterm e -> scan_entry list e | Snterml e l -> scan_entry list e | Slist0 s -> scan_symbol list s | Slist0sep s sep _ -> scan_symbol (scan_symbol list s) sep | Slist1 s -> scan_symbol list s | Slist1sep s sep _ -> scan_symbol (scan_symbol list s) sep | Sopt s -> scan_symbol list s | Sflag s -> scan_symbol list s | Stree t -> scan_tree list t | Svala _ s -> scan_symbol list s | Sself | Snext | Scut | Stoken _ -> list ] and scan_level list lev = let list = scan_tree list lev.lsuffix in let list = scan_tree list lev.lprefix in list and scan_levels list levs = List.fold_left scan_level list levs and scan_entry list entry = if List.memq entry list then list else match entry.edesc with [ Dlevels levs -> scan_levels [entry :: list] levs | Dparser _ -> list ] ; value all_entries_in_graph list entry = List.rev (scan_entry list entry); (* main *) value entries = ref []; value rec list_mem_right_assoc x = fun [ [] -> False | [(a, b) :: l] -> x = b || list_mem_right_assoc x l ] ; value rec expr_list = fun [ [] -> <:expr< [] >> | [x :: l] -> <:expr< [$str:String.escaped x$ :: $expr_list l$] >> ] ; value compile () = let _ = keywords.val := [] in let list = List.fold_left all_entries_in_graph [] entries.val in let list = List.filter (fun e -> List.memq e list) entries.val @ List.filter (fun e -> not (List.memq e entries.val)) list in let list = let set = ref [] in List.fold_right (fun entry list -> if List.mem entry.ename set.val then list else do { set.val := [entry.ename :: set.val]; [entry :: list] }) list [] in let pell = List.map compile_entry list in let pel = List.flatten pell in let si1 = <:str_item< value rec $list:pel$ >> in let si2 = let list = list_sort compare keywords.val in <:str_item< let lexer = Lazy.force P.lexer in List.iter (fun kw -> lexer.Plexing.tok_using ("", kw)) $expr_list list$ >> in let loc = Ploc.dummy in ([(si1, loc); (si2, loc)], Some loc) ; Pcaml.parse_implem.val := fun _ -> compile (); Pcaml.add_option "-strict_parsing" (Arg.Set strict_parsing) "Don't generate error recovering by trying continuations or first levels"; camlp5-rel8.00.02/compile/compile.sh000077500000000000000000000024171410261051500171630ustar00rootroot00000000000000#!/bin/sh -e ARGS= FILES= ENTRIES= while test "" != "$1"; do case $1 in -e) shift; if test "$ENTRIES" != ""; then ENTRIES="$ENTRIES; "; fi ENTRIES="$ENTRIES$1";; *.ml*) FILES="$FILES $1";; *) ARGS="$ARGS $1";; esac shift done cat $FILES | sed -e 's/Pcaml.parse_i.*$//' -e 's|/; ||g' | perl -n -e 'print unless /^\s*#load/' > tmp.ml echo "Compile.entries.val := [$ENTRIES];" >> tmp.ml > tmp.mli echo "${OCAMLN}c -g -c tmp.mli" 1>&2 ${OCAMLN}c -g -c tmp.mli echo "${OCAMLN}run$EXE ../meta/${CAMLP5N}r$EXE -nolib -I ../meta pa_macro.cmo pa_extend.cmo pa_macro_gram.cmo q_MLast.cmo -meta_action tmp.ml -o tmp.ppo" 1>&2 ${OCAMLN}run$EXE ../meta/${CAMLP5N}r$EXE -nolib -I ../meta pa_macro.cmo pa_extend.cmo pa_macro_gram.cmo q_MLast.cmo -meta_action tmp.ml -o tmp.ppo echo "${OCAMLN}c -g -I ../lib -I ../main -c -impl tmp.ppo" 1>&2 ${OCAMLN}c -g -I ../lib -I ../main -c -impl tmp.ppo echo "${RM} tmp.ppo" 1>&2 ${RM} tmp.ppo echo "${OCAMLN}run$EXE ../main/${CAMLP5N}$EXE ./compile.cmo ./tmp.cmo ../etc/pr_r.cmo ../etc/pr_ro.cmo ../etc/pr_rp.cmo $ARGS -sep "\n\n" -impl - < /dev/null" 1>&2 ${OCAMLN}run$EXE ../main/${CAMLP5N}$EXE ./compile.cmo ./tmp.cmo ../etc/pr_r.cmo ../etc/pr_ro.cmo ../etc/pr_rp.cmo $ARGS -sep "\n\n" -impl - < /dev/null #${RM} tmp.* camlp5-rel8.00.02/compile/strip-parser.pl000077500000000000000000000006341410261051500201660ustar00rootroot00000000000000#!/usr/bin/env perl while () { $_ =~ s/Plexer.gmake\s*\(\s*\)\s*/Lazy.force P.lexer/ ; $_ =~ s/Grammar.Entry.of_parser\s+gram\s+"[^"]+"//; next if /^\s*EXTEND/../^\s*END/ ; # next if /Grammar.Entry.of_parser/; next if /Grammar.Entry.gcreate/; next if /Grammar.Entry.create/; next if /^\s*#load/ ; die "MUST preprocess away IFDEFs first" if /IFDEF/ ; next if /DELETE_RULE/ ; print ; } camlp5-rel8.00.02/config/000077500000000000000000000000001410261051500150055ustar00rootroot00000000000000camlp5-rel8.00.02/config/.gitignore000066400000000000000000000000261410261051500167730ustar00rootroot00000000000000Makefile.cnf Makefile camlp5-rel8.00.02/config/Makefile.check000066400000000000000000000000051410261051500175140ustar00rootroot00000000000000all: camlp5-rel8.00.02/config/Makefile.tpl000066400000000000000000000017071410261051500172500ustar00rootroot00000000000000# Makefile.tpl,v NOVERBOSE=@ CAMLP5_COMM=OPT=$(OPT) EXE=$(EXE) OCAMLN=$(OCAMLN) MODE=$(MODE) COMPWITH=$(COMPWITH) CAMLP5N=$(CAMLP5N) ../tools/camlp5_comm.sh OCAMLC=@OPT=$(OPT) EXE=$(EXE) OCAMLN=$(OCAMLN) ../tools/ocamlc.sh OCAMLOPT=@OPT=$(OPT) EXE=$(EXE) OCAMLN=$(OCAMLN) ../tools/ocamlopt.sh DEBUG= OCAMLCFLAGS=$(DEBUG) MKDIR=mkdir -p RM=rm TEST_DIR=test `basename "$<"` = "$<" || { echo "File \"$<\" needs to be recompiled."; echo "Please run 'make' in directory '$$(dirname "$<")' first."; exit 1; } COMPWITH=old .SUFFIXES: .cmx .cmo .cmi .ml .mli .mli.cmi: $(NOVERBOSE) $(TEST_DIR) $(NOVERBOSE) $(CAMLP5_COMM) $< -o $*.ppi $(OCAMLC) $(OCAMLCFLAGS) -c -intf $*.ppi $(RM) -f $*.ppi .ml.cmo: $(NOVERBOSE) $(TEST_DIR) $(NOVERBOSE) $(CAMLP5_COMM) $< -o $*.ppo $(OCAMLC) $(OCAMLCFLAGS) -c -impl $*.ppo $(RM) -f $*.ppo .ml.cmx: $(NOVERBOSE) $(TEST_DIR) $(NOVERBOSE) $(CAMLP5_COMM) $< -o $*.ppo $(OCAMLOPT) $(OCAMLCFLAGS) -c -impl $*.ppo $(RM) -f $*.ppo camlp5-rel8.00.02/config/find_stuffversion.pl000077500000000000000000000016621410261051500211070ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use Data::Dumper ; { my $oversion = $ARGV[0] ; die "mal-formatted ocaml version detected: please report to maintainer with this output: ".Dumper(\@ARGV) unless $oversion =~ s,^(\d+(?:\.\d+)+)(?:[~-].*)?$,$1, ; if (-d "ocaml_stuff/$oversion" && -f "ocaml_src/lib/versdep/$oversion.ml") { print "$oversion\n"; exit ; } print STDERR "WARNING: missing directory ocaml_stuff/$oversion\n" if (! -d "ocaml_stuff/$oversion") ; print STDERR "WARNING: missing file ocaml_src/lib/versdep/$oversion.ml\n" if (! -f "ocaml_src/lib/versdep/$oversion.ml") ; $oversion =~ s,\.\d+$,.0, ; if (-d "ocaml_stuff/$oversion" && -f "ocaml_src/lib/versdep/$oversion.ml") { print STDERR "WARNING: FALLING BACK to saved info for ocaml version $oversion; please report to maintainer\n" ; print "$oversion\n"; exit ; } # let the configure script fail in the usual way print "$oversion\n"; } camlp5-rel8.00.02/configure000077500000000000000000000162511410261051500154540ustar00rootroot00000000000000#!/bin/sh # configure,v prefix='' bindir='' libdir='' mandir='' mode=S camlp5n=camlp5 ocamln=ocaml noopt=0 oversion='' if [ -f myconfig ]; then . ./myconfig fi # a local which command for sh which () { IFS=":" # set words separator in PATH to be ':' (it allows spaces in dirnames) for i in $PATH; do if test -z "$i"; then $i=.; fi if [ -f "$i/$1" ] ; then IFS=" " echo $i/$1 break fi done } # Parse command-line arguments while : ; do case "$1" in "") break;; -prefix|--prefix) prefix=$2; shift;; -bindir|--bindir) bindir=$2; shift;; -libdir|--libdir) libdir=$2; shift;; -mandir|--mandir) mandir=$2; shift;; -no-opt|--no-opt) noopt=1;; -oversion|--oversion) oversion=$2; shift;; -transitional|--transitional) mode=T;; -strict|--strict) mode=S;; -oname|--oname) ocamln=$2; shift;; -name|--name) camlp5n=$2; shift;; -help|--help) echo "Usage: configure [options]" echo "Options:" echo " -bindir , --bindir " echo " Directory where the binaries will be installed" echo " Default: same than command ocamlc" echo " -libdir , --libdir " echo " Directory where the camlp5 directory will be installed" echo " Default: same than 'ocamlc -where'" echo " -mandir , --mandir " echo " Directory where the manual pages will be installed" echo " Default: /../man" echo " -prefix , --prefix " echo " Set bindir, libdir and mandir respectively to" echo " /bin, /lib/ocaml, /man." echo " -no-opt, --no-opt" echo " do not use .opt versions of ocaml compilers" echo " -oversion " echo " specify an OCaml version on ocaml_stuff directory" echo " -transitional, --transitional" echo " compile in transitional mode" echo " -strict, --strict" echo " compile in strict mode" echo " -oname , --oname " echo " OCaml name (default: ocaml)" echo " -name , --name " echo " Camlp5 name (default: camlp5)" echo " -help, --help" echo " this message" exit 0;; *) echo "Unknown option \"$1\"." 1>&2; exit 2;; esac shift done if [ "$mode" = "T" -o "$mode" = "S" ]; then : else echo 1>&2 echo "Launch \"configure\" with the mode you want:" 1>&2 echo " --transitional" 1>&2 echo " --strict" 1>&2 echo 1>&2 exit 2 fi echo "mode=$mode" > myconfig # Sanity checks case "$prefix" in /*) ;; "") ;; *) echo "The -prefix directory must be absolute." 1>&2; exit 2;; esac case "$bindir" in /*) ;; "") ;; *) echo "The -bindir directory must be absolute." 1>&2; exit 2;; esac case "$libdir" in /*) ;; "") ;; *) echo "The -libdir directory must be absolute." 1>&2; exit 2;; esac case "$mandir" in /*) ;; "") ;; *) echo "The -mandir directory must be absolute." 1>&2; exit 2;; esac case "$camlp5n" in /*) ;; "") echo "Camlp5 name must not be empty." 1>&2; exit 2;; *) ;; esac # Check Ocaml ocamlc=${ocamln}c ocamlopt=${ocamln}opt ocamlrun=${ocamln}run if ${ocamln}c -v >/dev/null 2>&1; then : else echo "You need the command" ${ocamln}c "accessible in the path!" echo "Configuration script failed!" exit 1 fi # Check versions if [ "$oversion" = "" ]; then oversion=$(${ocamln}c -v | head -1 | sed 's/^.*version //; s/ .*$//') fi OVERSION=$(echo "$oversion" | sed -e 's/[ +].*$//') STUFFVERSION=$(./config/find_stuffversion.pl $OVERSION) if [ -d "ocaml_stuff/$STUFFVERSION" -a \ -f "ocaml_src/lib/versdep/$STUFFVERSION.ml" ] then : else echo echo "Sorry: the compatibility with ocaml version \"$oversion\"" echo "is not yet implemented. Please report." echo if [ -d "ocaml_stuff/$STUFFVERSION" ]; then echo "Information: file ocaml_src/lib/versdep/$STUFFVERSION.ml is missing." else echo "Information: directory ocaml_stuff/$STUFFVERSION is missing." fi echo echo "Configuration failed." # to give the ability to do "make steal": echo "OVERSION=$OVERSION" > config/Makefile echo "OCAMLN=$ocamln" >> config/Makefile exit 2 fi # Evaluate installation directories ocamlc_where=$($ocamlc -where 2>/dev/null) if [ "$?" != "0" ]; then ocamlc_where=$($ocamlc -v | tail -1 | sed -e 's/^.*: //') fi x=$ocamlc_where y=$(echo $x | sed -e 's|\\\\|/|g') x="$(echo 'Sys.os_type;;' | ocaml | egrep 'Win32|Cygwin')" if test "$x" = ""; then win=false; else win=true; fi x="$(echo 'Sys.os_type;;' | ocaml | grep 'Win32')" if test "$x" = ""; then win32=false; else win32=true; fi OLIBDIR="$y" if [ "$OVERSION" "<" "4.00" ]; then OCLIBDIR="." else OCLIBDIR="+compiler-libs" fi if test "$win" = "true"; then EXE=.exe else EXE= fi if test "$win32" = "true"; then EXT_OBJ=.obj EXT_LIB=.lib else EXT_OBJ=.o EXT_LIB=.a fi if test "$bindir" != ""; then BINDIR=$bindir elif test "$prefix" != ""; then BINDIR='$(PREFIX)/bin' else BINDIR=$(dirname "$(which $ocamlc)") fi if test "$libdir" != ""; then LIBDIR=$libdir elif test "$prefix" != ""; then LIBDIR='$(PREFIX)/lib/ocaml' else LIBDIR=$ocamlc_where fi if test "$mandir" != ""; then MANDIR=$mandir elif test "$prefix" != ""; then MANDIR='$(PREFIX)/man' else MANDIR=$(dirname "$BINDIR")/man fi OPT= if [ "$noopt" = "0" ] && $ocamlc.opt > /dev/null 2>&1 && $ocamlopt.opt > /dev/null 2>&1 then oversion_opt=$($ocamlopt.opt -v | head -1 | sed 's/^.*version //; s/ .*$//') if [ "$oversion" = "$oversion_opt" ]; then OPT=.opt fi fi if [ "$(ocamlc -w y 2>&1)" = "" ]; then OCAMLC_W_Y="-w y" else OCAMLC_W_Y="" fi if [ "$($ocamlc -warn-error +A-11 2>&1)" = "" ]; then WARNERR="-warn-error +A-11" else WARNERR="" fi if make -f config/Makefile.check --no-print-directory >/dev/null 2>&1; then NO_PR_DIR=--no-print-directory else NO_PR_DIR= fi VERSION="$(grep "value version =" main/pcaml.ml | sed -e 's/^[^"]*"\([^"]*\).*$/\1/')" ( echo MODE=$mode echo EXE=$EXE echo OPT=$OPT echo EXT_OBJ=$EXT_OBJ echo EXT_LIB=$EXT_LIB echo OVERSION=$STUFFVERSION echo VERSION=$VERSION echo OCAMLC_W_Y=\"$OCAMLC_W_Y\" echo WARNERR=\"$WARNERR\" echo NO_PR_DIR=$NO_PR_DIR echo OLIBDIR=$OLIBDIR echo OCLIBDIR=$OCLIBDIR if test "$prefix" != ""; then echo PREFIX=$prefix fi if test "$OVERSION" "<" "4.00.0"; then echo "OTOPP=\$(TOP)/ocaml_stuff/$STUFFVERSION/parsing" echo "OTOPW=\$(TOP)/ocaml_stuff/$STUFFVERSION/utils" else echo "OTOPP=$OCLIBDIR" echo "OTOPW=$OCLIBDIR" fi echo "OTOPU=\$(TOP)/ocaml_stuff/$STUFFVERSION/utils" echo BINDIR=$BINDIR echo LIBDIR=$LIBDIR echo MANDIR=$MANDIR echo OCAMLN=$ocamln echo CAMLP5N=$camlp5n ) > config/Makefile.cnf rm -f config/Makefile cat config/Makefile.tpl > config/Makefile echo >> config/Makefile cat config/Makefile.cnf >> config/Makefile cd ocaml_src/lib cp "versdep/$STUFFVERSION.ml" versdep.ml cd ../.. echo echo "Resulting configuration file (config/Makefile.cnf):" echo cat config/Makefile.cnf echo if [ "$mode" = "T" ]; then echo "=== transitional mode ===" else echo "=== strict mode ===" fi echo camlp5-rel8.00.02/doc/000077500000000000000000000000001410261051500143055ustar00rootroot00000000000000camlp5-rel8.00.02/doc/.gitignore000066400000000000000000000000531410261051500162730ustar00rootroot00000000000000*.aux *.bbl *.blg *.dvi *.log *.toc _build camlp5-rel8.00.02/doc/html/000077500000000000000000000000001410261051500152515ustar00rootroot00000000000000camlp5-rel8.00.02/doc/html/.gitignore000066400000000000000000000000131410261051500172330ustar00rootroot00000000000000*.html rss camlp5-rel8.00.02/doc/html/styles/000077500000000000000000000000001410261051500165745ustar00rootroot00000000000000camlp5-rel8.00.02/doc/html/styles/base.css000066400000000000000000000052441410261051500202250ustar00rootroot00000000000000/* base.css,v */ body { margin: 0 0 1px 0; background-color: rgb(189,225,255) } body { border: 0 } #menu { width: 21%; position: relative; float: left } #menu { border-top: 1px solid; border-left: 1px solid } #menu { font-size: 90% } #menu ul { padding: 0 } #menu li { margin-left: 1cm } #menu h1 { font-weight: normal; margin-bottom: 0 } #menu .subtitle { text-align: center; margin-top: 0; font-size: 80% } #menu .subtitle { text-transform: lowercase } #content { margin-left: 21.1%; padding: 0 5mm; background-color: white } #content { border: 1px solid } #content ul { margin-left: 1cm } #content ul ul { margin-left: 2mm } #content dl ul { margin-left: 2mm } #content dl p { margin-left: 0 } #content ol { margin-left: 1cm } #content p { text-align: justify } #content li { text-align: justify } #content dd { text-align: justify } #tableofcontents { display: table; margin: auto } #tableofcontents > ol { border: 1px solid; display: table-cell } #tableofcontents > ol { padding: 2mm 5mm 2mm 1cm } #tableofcontents ol { margin-left: 2mm } #tableofcontents li ul { margin-left: 0 } #tableofcontents li { text-align: left } #menu:target { position: relative; float: left } #menu:target { background-color: rgb(189,225,255) } #menumove { float: right; margin: 1mm; font-size: 80% } #menumove a { text-decoration: none } #menumove a:hover { text-decoration: underline overline } body { counter-reset: h2cnt } h1 { text-align: center } h2:before { content: counter(h2cnt) " - "; counter-increment: h2cnt } h2 { border: 1px solid; text-align: center; background: rgb(189,225,255) } h2 { counter-reset: h3cnt } h3:target { background-color: #cde } div:target { background-color: #cde } a.toplink { position: fixed; top: 0; right: 1mm; text-decoration: none } h3:before { content: counter(h2cnt) "." counter(h3cnt) " - "; counter-increment: h3cnt } h3 { counter-reset: h4cnt } h4:before { content: counter(h2cnt) "." counter(h3cnt) "." counter(h4cnt) " - "; counter-increment: h4cnt } p { margin: 1em 1cm } pre { border-left: silver solid 3px; margin-bottom: 1em; margin-left: 1.5cm; padding-left: 0; padding-right: 0.5em; line-height: 1.2 } dl { margin-left: 1cm } .half { width: 50% } .centered { margin: auto } .top { margin-top: 0; padding-top: 5mm } .bottom { margin-bottom: 0 } .trailer { margin-top: 3cm } .value { } .dangling { color: red; background: rgb(220,220,220) } .parenthesis { color: blue } .u { text-decoration: underline } @media print { body { background-color: white; border: 0 } #menu { display: none } #menumove { display: none } #content { margin: 0; border: 0 } #tableofcontents { display: none } .toplink { display: none } .trailer img { display: none } } camlp5-rel8.00.02/doc/htmlp/000077500000000000000000000000001410261051500154315ustar00rootroot00000000000000camlp5-rel8.00.02/doc/htmlp/.gitignore000066400000000000000000000001451410261051500174210ustar00rootroot00000000000000camlp5.aux camlp5.dvi camlp5.info* camlp5.log camlp5.pdf camlp5.ps camlp5.tex camlp5.texi camlp5.toc camlp5-rel8.00.02/doc/htmlp/Makefile000066400000000000000000000040051410261051500170700ustar00rootroot00000000000000# Makefile,v TOP=../.. include $(TOP)/config/Makefile H=../html OBJS=$H/index.html $H/about.html $H/ast_strict.html $H/ast_transi.html $H/bparsers.html $H/commands.html $H/conclusion.html $H/directives.html $H/extfun.html $H/fparsers.html $H/grammars.html $H/lexers.html $H/library.html $H/locations.html $H/macros.html $H/ml_ast.html $H/opretty.html $H/parsers.html $H/pcaml.html $H/pprintf.html $H/pragma.html $H/pretty.html $H/printers.html $H/ptools.html $H/q_ast.html $H/quot.html $H/redef.html $H/revsynt.html $H/scheme.html $H/sources.html $H/strict.html $H/syntext.html RSS=$H/rss/camlp5.rss INDEX=index.html NO_PR_DIR=--no-print-directory install-to-pages: ../html/index.html camlp5.info camlp5.dvi camlp5.pdf camlp5.ps test -d $(PAGESROOT) || (echo PAGESROOT $(PAGESROOT) not a directory; false) cp camlp5.dvi $(PAGESROOT)/doc/dvi/camlp5-$(VERSION).dvi cp camlp5.pdf $(PAGESROOT)/doc/pdf/camlp5-$(VERSION).pdf cp camlp5.ps $(PAGESROOT)/doc/ps/camlp5-$(VERSION).ps rm -rf $(PAGESROOT)/doc/htmlc && cp -r ../html $(PAGESROOT)/doc/htmlc tar -C .. -zcf $(PAGESROOT)/doc/htmlz/camlp5-$(VERSION).html.tgz html tar -zcf $(PAGESROOT)/doc/info/camlp5-$(VERSION).info.tgz camlp5.info* all: $(OBJS) $(RSS) info: @$(MAKE) $(NO_PR_DIR) camlp5.info H=. tex: @$(MAKE) $(NO_PR_DIR) camlp5.dvi H=. ps: @$(MAKE) $(NO_PR_DIR) camlp5.ps H=. pdf: @$(MAKE) $(NO_PR_DIR) camlp5.pdf H=. camlp5.info: html2texi $(OBJS) ./html2texi > camlp5.texi makeinfo --force camlp5.texi camlp5.dvi: camlp5.tex latex camlp5.tex latex camlp5.tex latex camlp5.tex camlp5.tex: html2latex $(OBJS) ./html2latex > camlp5.tex camlp5.ps: camlp5.dvi dvips -f- camlp5.dvi > camlp5.ps camlp5.pdf: camlp5.tex pdflatex camlp5.tex clean: rm -f $(OBJS) $(RSS) rm -f camlp5.texi camlp5.info* camlp5.ps rm -f camlp5.tex camlp5.dvi camlp5.log camlp5.toc camlp5.aux ../html/%.html: %.html menu.html trailer.html @mkdir -p ../html @rm -f $@ ./htmlp2html $< > $@ @chmod 444 $@ ../html/rss/%.rss: %.rss @mkdir -p ../html/rss @rm -f $@ cp $< $@ @chmod 444 $@ camlp5-rel8.00.02/doc/htmlp/about.html000066400000000000000000000025631410261051500174370ustar00rootroot00000000000000 About Camlp5

About Camlp5

Version
Home page
http://pauillac.inria.fr/~ddr/camlp5/
Author
Daniel de Rauglaudre, INRIA
History
The ideas behind Camlp5 were expressed in the 1990s by Michel Mauny. In 1996, Daniel de Rauglaudre implemented the first version named Camlp4 (the four "p" standing for "Pre-Processor-Pretty-Printer"). In 2002, Camlp4 was maintained by Michel Mauny, and later extended by Nicolas Pouillard, with different basic ideas, introducing some incompatibilities. In 2006, Daniel de Rauglaudre restarted this work, renaming it Camlp5.

camlp5-rel8.00.02/doc/htmlp/ast_strict.html000066400000000000000000004353551410261051500205150ustar00rootroot00000000000000 AST - strict

Syntax tree - strict mode

This chapter presents the Camlp5 syntax tree when Camlp5 is installed in strict mode.

Introduction

This syntax tree is defined in the module "MLast" provided by Camlp5. Each node corresponds to a syntactic entity of the corresponding type.

For example, the syntax tree of the statement "if" can be written:

  MLast.ExIfe loc e1 e2 e3

where "loc" is the location in the source, and "e1", "e2" and "e3" are respectively the expression after the "if", the one after the "then" and the one after the "else".

If a program needs to manipulate syntax trees, it can use the nodes defined in the module "MLast". The programmer must know how the concrete syntax is transformed into this abstract syntax.

A simpler solution is to use one of the quotation kits "q_MLast.cmo" or "q_ast.cmo". Both propose quotations which represent the abstract syntax (the nodes of the module "MLast") into concrete syntax with antiquotations to bind variables inside. The example above can be written:

  <:expr< if $e1$ then $e2$ else $e3$ >>

This representation is very interesting when one wants to manipulate complicated syntax trees. Here is an example taken from the Camlp5 sources themselves:

  <:expr<
    match try Some $f$ with [ Stream.Failure -> None ] with
    [ Some $p$ -> $e$
    | _ -> raise (Stream.Error $e2$) ]
  >>

This example was in a position of a pattern. In abstract syntax, it should have been written:

  MLast.ExMat _
    (MLast.ExTry _ (MLast.ExApp _ (MLast.ExUid _ (Ploc.VaVal "Some")) f)
       (Ploc.VaVal
          [(MLast.PaAcc _ (MLast.PaUid _ (Ploc.VaVal "Stream"))
             (MLast.PaUid _ (Ploc.VaVal "Failure")),
            Ploc.VaVal None, MLast.ExUid _ (Ploc.VaVal "None"))]))
    (Ploc.VaVal
       [(MLast.PaApp _ (MLast.PaUid _ (Ploc.VaVal "Some")) p,
         Ploc.VaVal None, e);
        (MLast.PaAny _, Ploc.VaVal None,
         MLast.ExApp _ (MLast.ExLid _ (Ploc.VaVal "raise"))
           (MLast.ExApp _
              (MLast.ExAcc _ (MLast.ExUid _ (Ploc.VaVal "Stream"))
                 (MLast.ExUid _ (Ploc.VaVal "Error")))
              e2))])

Which is less readable and much more complicated to build and update.

Instead of thinking of "a syntax tree", the programmer can think of "a piece of program".

Location

In all syntax tree nodes, the first parameter is the source location of the node.

In expressions

When a quotation is in the context of an expression, the location parameter is "loc" in the node and in all its possible sub-nodes. Example: if we consider the quotation:

  <:sig_item< value foo : int -> bool >>

This quotation, in a context of an expression, is equivalent to:

  MLast.SgVal loc (Ploc.VaVal "foo")
    (MLast.TyArr loc (MLast.TyLid loc (Ploc.VaVal "int"))
       (MLast.TyLid loc (Ploc.VaVal "bool")));

The name "loc" is predefined. However, it is possible to change it, using the argument "-loc" of the Camlp5 shell commands.

Consequently, if there is no variable "loc" defined in the context of the quotation, or if it is not of the good type, a semantic error occur in the OCaml compiler ("Unbound value loc").

Note that in the extensible grammars, the variable "loc" is bound, in all semantic actions, to the location of the rule.

If the created node has no location, the programmer can define a variable named "loc" equal to "Ploc.dummy".

In patterns

When a quotation is in the context of a pattern, the location parameter of all nodes and possible sub-nodes is set to the wildcard ("_"). The same example above:

  <:sig_item< value foo : int -> bool >>

is equivalent, in a pattern, to:

  MLast.SgVal _ (Ploc.VaVal "foo")
    (MLast.TyArr _ (MLast.TyLid _ (Ploc.VaVal "int"))
       (MLast.TyLid _ (Ploc.VaVal "bool")))

However, it is possible to generate a binding of the variable "loc" on the top node by writing a "colon" before the "less" in the quotation. The same example:

  <:sig_item:< value foo : int -> bool >>

is equivalent to:

  MLast.SgVal loc (Ploc.VaVal "foo")
    (MLast.TyArr _ (MLast.TyLid _ (Ploc.VaVal "int"))
       (MLast.TyLid _ (Ploc.VaVal "bool")))

Antiquotations

The expressions or patterns between dollar ($) characters are called antiquotations. In opposition to quotations which has its own syntax rules, the antiquotation is an area in the syntax of the enclosing context (expression or pattern). See the chapter about quotations.

If a quotation is in the context of an expression, the antiquotation must be an expression. It could be any expression, including function calls. Examples:

  value f e el = <:expr< [$e$ :: $loop False el$] >>;
  value patt_list p pl = <:patt< ( $list:[p::pl]$) >>;

If a quotation is in the context of an pattern, the antiquotation is a pattern. Any pattern is possible, including the wildcard character ("_"). Examples:

   fun [ <:expr< $lid:op$ $_$ $_$ >> -> op ]
   match p with [ <:patt< $_$ | $_$ >> -> Some p ]

Two kinds of antiquotations

Preliminary remark

In strict mode, we remark that most constructors defined of the module "MLast" are of type "Ploc.vala". This type is defined like this:

  type vala 'a =
    [ VaAnt of string
    | VaVal of 'a ]
  ;

The type argument is the real type of the node. For example, a value of type "bool" in transitional mode is frequently represented by a value of type "Ploc.vala bool".

The first case of the type "vala" corresponds to an antiquotation in the concrete syntax. The second case to a normal syntax situation, without antiquotation.

Example: in the "let" statement, the fact that it is "rec" or not is represented by a boolean. This boolean is, in the syntax tree, encapsulated with the type "Ploc.vala". The syntax tree of the two following lines:

  let x = y in z
  let rec x = y in z

start with, respectively:

  MLast.ExLet loc (Ploc.VaVal False)
    ... (* and so on *)

and:

  MLast.ExLet loc (Ploc.VaVal True)
    ... (* and so on *)

The case "Ploc.VaAnt s" is internally used by the parsers and by the quotation kit "q_ast.cmo" to record antiquotation strings representing the expression or the patterns having this value. For example, in this "let" statement:

  MLast.ExLet loc (Ploc.VaAnt s)
    ... (* and so on *)

The contents of this "s" is internally handled. For information, it contains the antiquotation string (kind included) together with representation of the location of the antiquotation in the quotation. See the next section.

Antiquoting

To antiquotate the fact that the "let" is with or without rec (a flag of type boolean), there are two ways.

direct antiquoting

The first way, hidding the type "Ploc.val", can be written with the antiquotation kind "flag":

  <:expr< let $flag:rf$ x = y in z >>

This corresponds to the syntax tree:

  MLast.ExLet loc (Ploc.VaVal rf)
     ... (* and so on *)

And, therefore, the type of the variable "rf" is simply "bool".

general antiquoting

The second way, introducing variables of type "Ploc.vala" can be written a kind prefixed by "_", namely here "_flag":

  <:expr< let $_flag:rf$ x = y in z >>

In that case, it corresponds to the syntax tree:

  MLast.ExLet loc rf
     ... (* and so on *)

And, therefore, the type of the variable "rf" is now "Ploc.vala bool".

Remarks

The first form of antiquotation ensures the compatibility with previous versions of Camlp5. The syntax tree is not the same, but the bound variables keep the same type.

All antiquotations kinds have these two forms: one with some name (e.g. "flag") and one with the same name prefixed by "a" (e.g. "aflag").

Nodes and Quotations

This section describes all nodes defined in the module "MLast" of Camlp5 and how to write them with quotations. Notice that, inside quotations, one is not restricted to these elementary cases, but any complex value can be used, resulting on possibly complex combined nodes.

The quotation forms are described here in revised syntax (like the rest of this document). In reality, it depends on which quotation kit is loaded:

  • If "q_MLast.cmo" is used, the revised syntax is mandatory: the quotations must be in that syntax without any extension.
  • If "q_ast.cmo" is used, the quotation syntax must be in the current user syntax with all extensions added to compile the file.

Last remark: in the following tables, the variables names give information of their types. The details can be found in the distributed source file "mLast.mli".

  • e, e1, e2, e3: expr
  • p, p1, p2, p3: patt
  • t, t1, t2, e3: ctyp
  • s: string
  • b: bool
  • me, me1, me2: module_expr
  • mt, mt1, mt2: module_type
  • le: list expr
  • lp: list patt
  • lt: list ctyp
  • ls: list string
  • lse: list (string * expr)
  • lpe: list (patt * expr)
  • lpp: list (patt * patt)
  • lpoee: list (patt * option expr * expr)
  • op: option patt
  • lcstri: list class_str_item
  • lcsigi: list class_sig_item

expr

Expressions of the language.

- access
<:expr< $e1$ . $e2$ >>
MLast.ExAcc loc e1 e2
- antiquotation (1)
<:expr< $anti:e$ >>
MLast.ExAnt loc e
- application
<:expr< $e1$ $e2$ >>
MLast.ExApp loc e1 e2
- array element
<:expr< $e1$ .( $e2$ ) >>
MLast.ExAre loc e1 e2
- array
<:expr< [| $list:le$ |] >>
MLast.ExArr loc (Ploc.VaVal le)

<:expr< [| $_list:le$ |] >>
MLast.ExArr loc le
- assert
<:expr< assert $e$ >>
MLast.ExAsr loc e
- assignment
<:expr< $e1$ := $e2$ >>
MLast.ExAss loc e1 e2
- big array element
<:expr< $e$ .{ $list:le$ } >>
MLast.ExBae loc e (Ploc.VaVal le)

<:expr< $e$ .{ $_list:le$ } >>
MLast.ExBae loc e le
- character constant
<:expr< $chr:s$ >>
MLast.ExChr loc (Ploc.VaVal s)

<:expr< $_chr:s$ >>
MLast.ExChr loc s
- coercion
<:expr< ($e$ :> $t2$) >>
MLast.ExCoe loc e None t2

<:expr< ($e$ : $t1$ :> $t2$) >>
MLast.ExCoe loc e (Some t1) t2
- float constant
<:expr< $flo:s$ >>
MLast.ExFlo loc (Ploc.VaVal s)

<:expr< $_flo:s$ >>
MLast.ExFlo loc s
- for (increasing)
<:expr< for $lid:s$ = $e1$ to $e2$ do { $list:le$ } >>
MLast.ExFor loc (Ploc.VaVal s) e1 e2 (Ploc.VaVal True) (Ploc.VaVal le)

<:expr< for $lid:s$ = $e1$ to $e2$ do { $_list:le$ } >>
MLast.ExFor loc (Ploc.VaVal s) e1 e2 (Ploc.VaVal True) le
- for (decreasing)
<:expr< for $lid:s$ = $e1$ downto $e2$ do { $list:le$ } >>
MLast.ExFor loc (Ploc.VaVal s) e1 e2 (Ploc.VaVal False) (Ploc.VaVal le)

<:expr< for $lid:s$ = $e1$ downto $e2$ do { $_list:le$ } >>
MLast.ExFor loc (Ploc.VaVal s) e1 e2 (Ploc.VaVal False) le
- for
<:expr< for $lid:s$ = $e1$ $to:b$ $e2$ do { $list:le$ } >>
MLast.ExFor loc (Ploc.VaVal s) e1 e2 (Ploc.VaVal b) (Ploc.VaVal le)

<:expr< for $lid:s$ = $e1$ $to:b$ $e2$ do { $_list:le$ } >>
MLast.ExFor loc (Ploc.VaVal s) e1 e2 (Ploc.VaVal b) le

<:expr< for $lid:s$ = $e1$ $_to:b$ $e2$ do { $list:le$ } >>
MLast.ExFor loc (Ploc.VaVal s) e1 e2 b (Ploc.VaVal le)

<:expr< for $lid:s$ = $e1$ $_to:b$ $e2$ do { $_list:le$ } >>
MLast.ExFor loc (Ploc.VaVal s) e1 e2 b le

<:expr< for $_lid:s$ = $e1$ to $e2$ do { $list:le$ } >>
MLast.ExFor loc s e1 e2 (Ploc.VaVal True) (Ploc.VaVal le)

<:expr< for $_lid:s$ = $e1$ to $e2$ do { $_list:le$ } >>
MLast.ExFor loc s e1 e2 (Ploc.VaVal True) le

<:expr< for $_lid:s$ = $e1$ downto $e2$ do { $list:le$ } >>
MLast.ExFor loc s e1 e2 (Ploc.VaVal False) (Ploc.VaVal le)

<:expr< for $_lid:s$ = $e1$ downto $e2$ do { $_list:le$ } >>
MLast.ExFor loc s e1 e2 (Ploc.VaVal False) le

<:expr< for $_lid:s$ = $e1$ $to:b$ $e2$ do { $list:le$ } >>
MLast.ExFor loc s e1 e2 (Ploc.VaVal b) (Ploc.VaVal le)

<:expr< for $_lid:s$ = $e1$ $to:b$ $e2$ do { $_list:le$ } >>
MLast.ExFor loc s e1 e2 (Ploc.VaVal b) le

<:expr< for $_lid:s$ = $e1$ $_to:b$ $e2$ do { $list:le$ } >>
MLast.ExFor loc s e1 e2 b (Ploc.VaVal le)

<:expr< for $_lid:s$ = $e1$ $_to:b$ $e2$ do { $_list:le$ } >>
MLast.ExFor loc s e1 e2 b le
- function
<:expr< fun [ $list:lpee$ ] >>
MLast.ExFun loc (Ploc.VaVal lpee)

<:expr< fun [ $_list:lpee$ ] >>
MLast.ExFun loc lpee
- if
<:expr< if $e1$ then $e2$ else $e3$ >>
MLast.ExIfe loc e1 e2 e3
- integer constant
<:expr< $int:s1$ >>
MLast.ExInt loc (Ploc.VaVal s1) ""

<:expr< $_int:s1$ >>
MLast.ExInt loc s1 ""
- integer 32 bits
<:expr< $int32:s1$ >>
MLast.ExInt loc (Ploc.VaVal s1) "l"

<:expr< $_int32:s1$ >>
MLast.ExInt loc s1 "l"
- integer 64 bits
<:expr< $int64:s1$ >>
MLast.ExInt loc (Ploc.VaVal s1) "L"

<:expr< $_int64:s1$ >>
MLast.ExInt loc s1 "L"
- native integer
<:expr< $nativeint:s1$ >>
MLast.ExInt loc (Ploc.VaVal s1) "n"

<:expr< $_nativeint:s1$ >>
MLast.ExInt loc s1 "n"
- label
<:expr< ~{$p$} >>
MLast.ExLab loc p (Ploc.VaVal None)

<:expr< ~{$p$ = $e$} >>
MLast.ExLab loc p (Ploc.VaVal (Some e))

<:expr< ~{$p$ $opt:oe$} >>
MLast.ExLab loc p (Ploc.VaVal oe)

<:expr< ~{$p$ $_opt:oe$} >>
MLast.ExLab loc p oe
- lazy
<:expr< lazy $e$ >>
MLast.ExLaz loc e
- let rec
<:expr< let rec $list:lpe$ in $e$ >>
MLast.ExLet loc (Ploc.VaVal True) (Ploc.VaVal lpe) e

<:expr< let rec $_list:lpe$ in $e$ >>
MLast.ExLet loc (Ploc.VaVal True) lpe e
- let not rec
<:expr< let $list:lpe$ in $e$ >>
MLast.ExLet loc (Ploc.VaVal False) (Ploc.VaVal lpe) e

<:expr< let $_list:lpe$ in $e$ >>
MLast.ExLet loc (Ploc.VaVal False) lpe e
- let
<:expr< let $flag:b$ $list:lpe$ in $e$ >>
MLast.ExLet loc (Ploc.VaVal b) (Ploc.VaVal lpe) e

<:expr< let $flag:b$ $_list:lpe$ in $e$ >>
MLast.ExLet loc (Ploc.VaVal b) lpe e

<:expr< let $_flag:b$ $list:lpe$ in $e$ >>
MLast.ExLet loc b (Ploc.VaVal lpe) e

<:expr< let $_flag:b$ $_list:lpe$ in $e$ >>
MLast.ExLet loc b lpe e
- lowercase identifier
<:expr< $lid:s$ >>
MLast.ExLid loc (Ploc.VaVal s)

<:expr< $_lid:s$ >>
MLast.ExLid loc s
- let module
<:expr< let module $uid:s$ = $me$ in $e$ >>
MLast.ExLmd loc (Ploc.VaVal s) me e

<:expr< let module $_uid:s$ = $me$ in $e$ >>
MLast.ExLmd loc s me e
- match
<:expr< match $e$ with [ $list:lpee$ ] >>
MLast.ExMat loc e (Ploc.VaVal lpee)

<:expr< match $e$ with [ $_list:lpee$ ] >>
MLast.ExMat loc e lpee
- new
<:expr< new $list:ls$ >>
MLast.ExNew loc (Ploc.VaVal ls)

<:expr< new $_list:ls$ >>
MLast.ExNew loc ls
- object expression
<:expr< object $list:lcsi$ end >>
MLast.ExObj loc (Ploc.VaVal None) (Ploc.VaVal lcsi)

<:expr< object $_list:lcsi$ end >>
MLast.ExObj loc (Ploc.VaVal None) lcsi

<:expr< object ($p$) $list:lcsi$ end >>
MLast.ExObj loc (Ploc.VaVal (Some p)) (Ploc.VaVal lcsi)

<:expr< object ($p$) $_list:lcsi$ end >>
MLast.ExObj loc (Ploc.VaVal (Some p)) lcsi

<:expr< object $opt:op$ $list:lcsi$ end >>
MLast.ExObj loc (Ploc.VaVal op) (Ploc.VaVal lcsi)

<:expr< object $opt:op$ $_list:lcsi$ end >>
MLast.ExObj loc (Ploc.VaVal op) lcsi

<:expr< object $_opt:op$ $list:lcsi$ end >>
MLast.ExObj loc op (Ploc.VaVal lcsi)

<:expr< object $_opt:op$ $_list:lcsi$ end >>
MLast.ExObj loc op lcsi
- option label
<:expr< ?{$p$} >>
MLast.ExOlb loc p (Ploc.VaVal None)

<:expr< ?{$p$ = $e$} >>
MLast.ExOlb loc p (Ploc.VaVal (Some e))

<:expr< ?{$p$ $opt:oe$} >>
MLast.ExOlb loc p (Ploc.VaVal oe)

<:expr< ?{$p$ $_opt:oe$} >>
MLast.ExOlb loc p oe
- override
<:expr< {< $list:lse$ >} >>
MLast.ExOvr loc (Ploc.VaVal lse)

<:expr< {< $_list:lse$ >} >>
MLast.ExOvr loc lse
- module packing
<:expr< (module $me$) >>
MLast.ExPck loc me None

<:expr< (module $me$ : $mt$) >>
MLast.ExPck loc me (Some mt)
- record
<:expr< {$list:lpe$} >>
MLast.ExRec loc (Ploc.VaVal lpe) None

<:expr< {($e$) with $list:lpe$} >>
MLast.ExRec loc (Ploc.VaVal lpe) (Some e)

<:expr< {$_list:lpe$} >>
MLast.ExRec loc lpe None

<:expr< {($e$) with $_list:lpe$} >>
MLast.ExRec loc lpe (Some e)
- sequence
<:expr< do { $list:le$ } >>
MLast.ExSeq loc (Ploc.VaVal le)

<:expr< do { $_list:le$ } >>
MLast.ExSeq loc le
- method call
<:expr< $e$ # $s$ >>
MLast.ExSnd loc e (Ploc.VaVal s)

<:expr< $e$ # $_:s$ >>
MLast.ExSnd loc e s
- string element
<:expr< $e1$ .[ $e2$ ] >>
MLast.ExSte loc e1 e2
- string
<:expr< $str:s$ >>
MLast.ExStr loc (Ploc.VaVal s)

<:expr< $_str:s$ >>
MLast.ExStr loc s
- try
<:expr< try $e$ with [ $list:lpee$ ] >>
MLast.ExTry loc e (Ploc.VaVal lpee)

<:expr< try $e$ with [ $_list:lpee$ ] >>
MLast.ExTry loc e lpee
- t-uple
<:expr< ($list:le$) >>
MLast.ExTup loc (Ploc.VaVal le)

<:expr< ($_list:le$) >>
MLast.ExTup loc le
- type constraint
<:expr< ($e$ : $t$) >>
MLast.ExTyc loc e t
- uppercase identifier
<:expr< $uid:s$ >>
MLast.ExUid loc (Ploc.VaVal s)

<:expr< $_uid:s$ >>
MLast.ExUid loc s
- variant
<:expr< ` $s$ >>
MLast.ExVrn loc (Ploc.VaVal s)

<:expr< ` $_:s$ >>
MLast.ExVrn loc s
- while
<:expr< while $e$ do { $list:le$ } >>
MLast.ExWhi loc e (Ploc.VaVal le)

<:expr< while $e$ do { $_list:le$ } >>
MLast.ExWhi loc e le
- extra node (2)
... no representation ...
MLast.ExXtr loc s oe
(1)

Node used in the quotation expanders to tells at conversion to OCaml compiler syntax tree time, that all locations of the sub-tree is correcty located in the quotation. By default, in quotations, the locations of all generated nodes are the location of the whole quotation. This node allows to make an exception to this rule, since we know that the antiquotation belongs to the universe of the enclosing program. See the chapter about quotations and, in particular, its section about antiquotations.

(2)

Extra node internally used by the quotation kit "q_ast.cmo" to build antiquotations of expressions.

patt

Patterns of the language.

- access
<:patt< $p1$ . $p2$ >>
MLast.PaAcc loc p1 p2
- alias
<:patt< ($p1$ as $p2$) >>
MLast.PaAli loc p1 p2
- antiquotation (1)
<:patt< $anti:p$ >>
MLast.PaAnt loc p
- wildcard
<:patt< _ >>
MLast.PaAny loc
- application
<:patt< $p1$ $p2$ >>
MLast.PaApp loc p1 p2
- array
<:patt< [| $list:lp$ |] >>
MLast.PaArr loc (Ploc.VaVal lp)

<:patt< [| $_list:lp$ |] >>
MLast.PaArr loc lp
- character
<:patt< $chr:s$ >>
MLast.PaChr loc (Ploc.VaVal s)

<:patt< $_chr:s$ >>
MLast.PaChr loc s
- float
<:patt< $flo:s$ >>
MLast.PaFlo loc (Ploc.VaVal s)

<:patt< $_flo:s$ >>
MLast.PaFlo loc s
- integer constant
<:patt< $int:s1$ >>
MLast.PaInt loc (Ploc.VaVal s1) ""

<:patt< $_int:s1$ >>
MLast.PaInt loc s1 ""
- integer 32 bits
<:patt< $int32:s1$ >>
MLast.PaInt loc (Ploc.VaVal s1) "l"

<:patt< $_int32:s1$ >>
MLast.PaInt loc s1 "l"
- integer 64 bits
<:patt< $int64:s1$ >>
MLast.PaInt loc (Ploc.VaVal s1) "L"

<:patt< $_int64:s1$ >>
MLast.PaInt loc s1 "L"
- native integer
<:patt< $nativeint:s1$ >>
MLast.PaInt loc (Ploc.VaVal s1) "n"

<:patt< $_nativeint:s1$ >>
MLast.PaInt loc s1 "n"
- label
<:patt< ~{$p1$} >>
MLast.PaLab loc p1 (Ploc.VaVal None)

<:patt< ~{$p1$ = $p2$} >>
MLast.PaLab loc p1 (Ploc.VaVal (Some p2))

<:patt< ~{$p1$ $opt:op2$} >>
MLast.PaLab loc p1 (Ploc.VaVal op2)

<:patt< ~{$p1$ $_opt:op2$} >>
MLast.PaLab loc p1 op2
- lazy
<:patt< lazy $p$ >>
MLast.PaLaz loc p
- lowercase identifier
<:patt< $lid:s$ >>
MLast.PaLid loc (Ploc.VaVal s)

<:patt< $_lid:s$ >>
MLast.PaLid loc s
- new type
<:patt< (type $lid:s$) >>
MLast.PaNty loc (Ploc.VaVal s)

<:patt< (type $_lid:s$) >>
MLast.PaNty loc s
- option label
<:patt< ?{$p$} >>
MLast.PaOlb loc p (Ploc.VaVal None)

<:patt< ?{$p$ = $e$} >>
MLast.PaOlb loc p (Ploc.VaVal (Some e))

<:patt< ?{$p$ $opt:oe$} >>
MLast.PaOlb loc p (Ploc.VaVal oe)

<:patt< ?{$p$ $_opt:oe$} >>
MLast.PaOlb loc p oe
- or
<:patt< $p1$ | $p2$ >>
MLast.PaOrp loc p1 p2
- record
<:patt< { $list:lpp$ } >>
MLast.PaRec loc (Ploc.VaVal lpp)

<:patt< { $_list:lpp$ } >>
MLast.PaRec loc lpp
- range
<:patt< $p1$ .. $p2$ >>
MLast.PaRng loc p1 p2
- string
<:patt< $str:s$ >>
MLast.PaStr loc (Ploc.VaVal s)

<:patt< $_str:s$ >>
MLast.PaStr loc s
- t-uple
<:patt< ($list:lp$) >>
MLast.PaTup loc (Ploc.VaVal lp)

<:patt< ($_list:lp$) >>
MLast.PaTup loc lp
- type constraint
<:patt< ($p$ : $t$) >>
MLast.PaTyc loc p t
- type pattern
<:patt< # $list:ls$ >>
MLast.PaTyp loc (Ploc.VaVal ls)

<:patt< # $_list:ls$ >>
MLast.PaTyp loc ls
- uppercase identifier
<:patt< $uid:s$ >>
MLast.PaUid loc (Ploc.VaVal s)

<:patt< $_uid:s$ >>
MLast.PaUid loc s
- module unpacking
<:patt< (module $uid:s$) >>
MLast.PaUnp loc (Ploc.VaVal s) None

<:patt< (module $uid:s$ : $mt$) >>
MLast.PaUnp loc (Ploc.VaVal s) (Some mt)

<:patt< (module $_uid:s$) >>
MLast.PaUnp loc s None

<:patt< (module $_uid:s$ : $mt$) >>
MLast.PaUnp loc s (Some mt)
- variant
<:patt< ` $s$ >>
MLast.PaVrn loc (Ploc.VaVal s)

<:patt< ` $_:s$ >>
MLast.PaVrn loc s
- extra node (2)
... no representation ...
MLast.PaXtr loc s op
(1) Node used to specify an antiquotation area, like for the equivalent node in expressions. See above.
(2) Extra node internally used by the quotation kit "q_ast.cmo" to build antiquotations of patterns.

ctyp

Type expressions of the language.

- access
<:ctyp< $t1$ . $t2$ >>
MLast.TyAcc loc t1 t2
- alias
<:ctyp< $t1$ as $t2$ >>
MLast.TyAli loc t1 t2
- wildcard
<:ctyp< _ >>
MLast.TyAny loc
- application
<:ctyp< $t1$ $t2$ >>
MLast.TyApp loc t1 t2
- arrow
<:ctyp< $t1$ -> $t2$ >>
MLast.TyArr loc t1 t2
- class
<:ctyp< # $list:ls$ >>
MLast.TyCls loc (Ploc.VaVal ls)

<:ctyp< # $_list:ls$ >>
MLast.TyCls loc ls
- label
<:ctyp< ~$s$: $t$ >>
MLast.TyLab loc (Ploc.VaVal s) t

<:ctyp< ~$_:s$: $t$ >>
MLast.TyLab loc s t
- lowercase identifier
<:ctyp< $lid:s$ >>
MLast.TyLid loc (Ploc.VaVal s)

<:ctyp< $_lid:s$ >>
MLast.TyLid loc s
- manifest
<:ctyp< $t1$ == private $t2$ >>
MLast.TyMan loc t1 (Ploc.VaVal True) t2

<:ctyp< $t1$ == $t2$ >>
MLast.TyMan loc t1 (Ploc.VaVal False) t2

<:ctyp< $t1$ == $priv:b$ $t2$ >>
MLast.TyMan loc t1 (Ploc.VaVal b) t2

<:ctyp< $t1$ == $_priv:b$ $t2$ >>
MLast.TyMan loc t1 b t2
- object
<:ctyp< < $list:lst$ .. > >>
MLast.TyObj loc (Ploc.VaVal lst) (Ploc.VaVal True)

<:ctyp< < $list:lst$ > >>
MLast.TyObj loc (Ploc.VaVal lst) (Ploc.VaVal False)

<:ctyp< < $list:lst$ $flag:b$ > >>
MLast.TyObj loc (Ploc.VaVal lst) (Ploc.VaVal b)

<:ctyp< < $list:lst$ $_flag:b$ > >>
MLast.TyObj loc (Ploc.VaVal lst) b

<:ctyp< < $_list:lst$ .. > >>
MLast.TyObj loc lst (Ploc.VaVal True)

<:ctyp< < $_list:lst$ > >>
MLast.TyObj loc lst (Ploc.VaVal False)

<:ctyp< < $_list:lst$ $flag:b$ > >>
MLast.TyObj loc lst (Ploc.VaVal b)

<:ctyp< < $_list:lst$ $_flag:b$ > >>
MLast.TyObj loc lst b
- option label
<:ctyp< ?$s$: $t$ >>
MLast.TyOlb loc (Ploc.VaVal s) t

<:ctyp< ?$_:s$: $t$ >>
MLast.TyOlb loc s t
- package
<:ctyp< (module $mt$) >>
MLast.TyPck loc mt
- polymorph
<:ctyp< ! $list:ls$ . $t$ >>
MLast.TyPol loc (Ploc.VaVal ls) t

<:ctyp< ! $_list:ls$ . $t$ >>
MLast.TyPol loc ls t
- variable
<:ctyp< '$s$ >>
MLast.TyQuo loc (Ploc.VaVal s)

<:ctyp< '$_:s$ >>
MLast.TyQuo loc s
- record
<:ctyp< { $list:llsbt$ } >>
MLast.TyRec loc (Ploc.VaVal llsbt)

<:ctyp< { $_list:llsbt$ } >>
MLast.TyRec loc llsbt
- sum
<:ctyp< [ $list:llslt$ ] >>
MLast.TySum loc (Ploc.VaVal llslt)

<:ctyp< [ $_list:llslt$ ] >>
MLast.TySum loc llslt
- t-uple
<:ctyp< ( $list:lt$ ) >>
MLast.TyTup loc (Ploc.VaVal lt)

<:ctyp< ( $_list:lt$ ) >>
MLast.TyTup loc lt
- uppercase identifier
<:ctyp< $uid:s$ >>
MLast.TyUid loc (Ploc.VaVal s)

<:ctyp< $_uid:s$ >>
MLast.TyUid loc s
- variant
<:ctyp< [ = $list:lpv$ ] >>
MLast.TyVrn loc (Ploc.VaVal lpv) None

<:ctyp< [ > $list:lpv$ ] >>
MLast.TyVrn loc (Ploc.VaVal lpv) (Some None)

<:ctyp< [ < $list:lpv$ ] >>
MLast.TyVrn loc (Ploc.VaVal lpv) (Some (Some (Ploc.VaVal [])))

<:ctyp< [ < $list:lpv$ > $list:ls$ ] >>
MLast.TyVrn loc (Ploc.VaVal lpv) (Some (Some (Ploc.VaVal ls)))

<:ctyp< [ < $list:lpv$ > $_list:ls$ ] >>
MLast.TyVrn loc (Ploc.VaVal lpv) (Some (Some ls))

<:ctyp< [ = $_list:lpv$ ] >>
MLast.TyVrn loc lpv None

<:ctyp< [ > $_list:lpv$ ] >>
MLast.TyVrn loc lpv (Some None)

<:ctyp< [ < $_list:lpv$ ] >>
MLast.TyVrn loc lpv (Some (Some (Ploc.VaVal [])))

<:ctyp< [ < $_list:lpv$ > $list:ls$ ] >>
MLast.TyVrn loc lpv (Some (Some (Ploc.VaVal ls)))

<:ctyp< [ < $_list:lpv$ > $_list:ls$ ] >>
MLast.TyVrn loc lpv (Some (Some ls))
- extra node (1)
... no representation ...
MLast.TyXtr loc s ot
(1) Extra node internally used by the quotation kit "q_ast.cmo" to build antiquotations of types.

modules...

str_item

Structure items, i.e. phrases in a ".ml" file or "struct" elements.

- class declaration
<:str_item< class $list:lcice$ >>
MLast.StCls loc (Ploc.VaVal lcice)

<:str_item< class $_list:lcice$ >>
MLast.StCls loc lcice
- class type declaration
<:str_item< class type $list:lcict$ >>
MLast.StClt loc (Ploc.VaVal lcict)

<:str_item< class type $_list:lcict$ >>
MLast.StClt loc lcict
- declare
<:str_item< declare $list:lsi$ end >>
MLast.StDcl loc (Ploc.VaVal lsi)

<:str_item< declare $_list:lsi$ end >>
MLast.StDcl loc lsi
- directive
<:str_item< # $lid:s$ >>
MLast.StDir loc (Ploc.VaVal s) (Ploc.VaVal None)

<:str_item< # $lid:s$ $e$ >>
MLast.StDir loc (Ploc.VaVal s) (Ploc.VaVal (Some e))

<:str_item< # $lid:s$ $opt:oe$ >>
MLast.StDir loc (Ploc.VaVal s) (Ploc.VaVal oe)

<:str_item< # $lid:s$ $_opt:oe$ >>
MLast.StDir loc (Ploc.VaVal s) oe

<:str_item< # $_lid:s$ >>
MLast.StDir loc s (Ploc.VaVal None)

<:str_item< # $_lid:s$ $e$ >>
MLast.StDir loc s (Ploc.VaVal (Some e))

<:str_item< # $_lid:s$ $opt:oe$ >>
MLast.StDir loc s (Ploc.VaVal oe)

<:str_item< # $_lid:s$ $_opt:oe$ >>
MLast.StDir loc s oe
- exception
<:str_item< exception $uid:s$ >>
MLast.StExc loc (Ploc.VaVal s) (Ploc.VaVal []) (Ploc.VaVal [])

<:str_item< exception $uid:s$ of $list:lt$ >>
MLast.StExc loc (Ploc.VaVal s) (Ploc.VaVal lt) (Ploc.VaVal [])

<:str_item< exception $uid:s$ = $list:ls$ >>
MLast.StExc loc (Ploc.VaVal s) (Ploc.VaVal []) (Ploc.VaVal ls)

<:str_item< exception $uid:s$ of $list:lt$ = $list:ls$ >>
MLast.StExc loc (Ploc.VaVal s) (Ploc.VaVal lt) (Ploc.VaVal ls)

<:str_item< exception $uid:s$ = $_list:ls$ >>
MLast.StExc loc (Ploc.VaVal s) (Ploc.VaVal []) ls

<:str_item< exception $uid:s$ of $list:lt$ = $_list:ls$ >>
MLast.StExc loc (Ploc.VaVal s) (Ploc.VaVal lt) ls

<:str_item< exception $uid:s$ of $_list:lt$ >>
MLast.StExc loc (Ploc.VaVal s) lt (Ploc.VaVal [])

<:str_item< exception $uid:s$ of $_list:lt$ = $list:ls$ >>
MLast.StExc loc (Ploc.VaVal s) lt (Ploc.VaVal ls)

<:str_item< exception $uid:s$ of $_list:lt$ = $_list:ls$ >>
MLast.StExc loc (Ploc.VaVal s) lt ls

<:str_item< exception $_uid:s$ >>
MLast.StExc loc s (Ploc.VaVal []) (Ploc.VaVal [])

<:str_item< exception $_uid:s$ of $list:lt$ >>
MLast.StExc loc s (Ploc.VaVal lt) (Ploc.VaVal [])

<:str_item< exception $_uid:s$ = $list:ls$ >>
MLast.StExc loc s (Ploc.VaVal []) (Ploc.VaVal ls)

<:str_item< exception $_uid:s$ of $list:lt$ = $list:ls$ >>
MLast.StExc loc s (Ploc.VaVal lt) (Ploc.VaVal ls)

<:str_item< exception $_uid:s$ = $_list:ls$ >>
MLast.StExc loc s (Ploc.VaVal []) ls

<:str_item< exception $_uid:s$ of $list:lt$ = $_list:ls$ >>
MLast.StExc loc s (Ploc.VaVal lt) ls

<:str_item< exception $_uid:s$ of $_list:lt$ >>
MLast.StExc loc s lt (Ploc.VaVal [])

<:str_item< exception $_uid:s$ of $_list:lt$ = $list:ls$ >>
MLast.StExc loc s lt (Ploc.VaVal ls)

<:str_item< exception $_uid:s$ of $_list:lt$ = $_list:ls$ >>
MLast.StExc loc s lt ls
- expression
<:str_item< $exp:e$ >>
MLast.StExp loc e
- external
<:str_item< external $s$ : $t$ = $list:ls$ >>
MLast.StExt loc (Ploc.VaVal s) t (Ploc.VaVal ls)

<:str_item< external $s$ : $t$ = $_list:ls$ >>
MLast.StExt loc (Ploc.VaVal s) t ls

<:str_item< external $_:s$ : $t$ = $list:ls$ >>
MLast.StExt loc s t (Ploc.VaVal ls)

<:str_item< external $_:s$ : $t$ = $_list:ls$ >>
MLast.StExt loc s t ls
- include
<:str_item< include $me$ >>
MLast.StInc loc me
- module rec
<:str_item< module rec $list:lsme$ >>
MLast.StMod loc (Ploc.VaVal True) (Ploc.VaVal lsme)

<:str_item< module rec $_list:lsme$ >>
MLast.StMod loc (Ploc.VaVal True) lsme
- module non rec
<:str_item< module $list:lsme$ >>
MLast.StMod loc (Ploc.VaVal False) (Ploc.VaVal lsme)

<:str_item< module $_list:lsme$ >>
MLast.StMod loc (Ploc.VaVal False) lsme
- module
<:str_item< module $flag:b$ $list:lsme$ >>
MLast.StMod loc (Ploc.VaVal b) (Ploc.VaVal lsme)

<:str_item< module $flag:b$ $_list:lsme$ >>
MLast.StMod loc (Ploc.VaVal b) lsme

<:str_item< module $_flag:b$ $list:lsme$ >>
MLast.StMod loc b (Ploc.VaVal lsme)

<:str_item< module $_flag:b$ $_list:lsme$ >>
MLast.StMod loc b lsme
- module type
<:str_item< module type $s$ = $mt$ >>
MLast.StMty loc (Ploc.VaVal s) mt

<:str_item< module type $_:s$ = $mt$ >>
MLast.StMty loc s mt
- open
<:str_item< open $list:ls$ >>
MLast.StOpn loc (Ploc.VaVal ls)

<:str_item< open $_list:ls$ >>
MLast.StOpn loc ls
- type declaration
<:str_item< type $list:ltd$ >>
MLast.StTyp loc (Ploc.VaVal ltd)

<:str_item< type $_list:ltd$ >>
MLast.StTyp loc ltd
- ... internal use ... (1)
<:str_item< # $str:s$ $list:lsil$ >>
MLast.StUse loc (Ploc.VaVal s) (Ploc.VaVal lsil)

<:str_item< # $str:s$ $_list:lsil$ >>
MLast.StUse loc (Ploc.VaVal s) lsil

<:str_item< # $_str:s$ $list:lsil$ >>
MLast.StUse loc s (Ploc.VaVal lsil)

<:str_item< # $_str:s$ $_list:lsil$ >>
MLast.StUse loc s lsil
- value rec
<:str_item< value rec $list:lpe$ >>
MLast.StVal loc (Ploc.VaVal True) (Ploc.VaVal lpe)

<:str_item< value rec $_list:lpe$ >>
MLast.StVal loc (Ploc.VaVal True) lpe
- value non rec
<:str_item< value $list:lpe$ >>
MLast.StVal loc (Ploc.VaVal False) (Ploc.VaVal lpe)

<:str_item< value $_list:lpe$ >>
MLast.StVal loc (Ploc.VaVal False) lpe
- value
<:str_item< value $flag:b$ $list:lpe$ >>
MLast.StVal loc (Ploc.VaVal b) (Ploc.VaVal lpe)

<:str_item< value $flag:b$ $_list:lpe$ >>
MLast.StVal loc (Ploc.VaVal b) lpe

<:str_item< value $_flag:b$ $list:lpe$ >>
MLast.StVal loc b (Ploc.VaVal lpe)

<:str_item< value $_flag:b$ $_list:lpe$ >>
MLast.StVal loc b lpe
- extra node (2)
... no representation ...
MLast.StXtr loc s ot
(1)

Node internally used to specify a different file name applying to the whole subtree. This is generated by the directive "use" and used when converting to the OCaml syntax tree which needs the file name in its location type.

(2)

Extra node internally used by the quotation kit "q_ast.cmo" to build antiquotations of structure items.

sig_item

Signature items, i.e. phrases in a ".mli" file or elements inside "sig ... end".

- class
<:sig_item< class $list:lcict$ >>
MLast.SgCls loc (Ploc.VaVal lcict)

<:sig_item< class $_list:lcict$ >>
MLast.SgCls loc lcict
- class type
<:sig_item< class type $list:lcict$ >>
MLast.SgClt loc (Ploc.VaVal lcict)

<:sig_item< class type $_list:lcict$ >>
MLast.SgClt loc lcict
- declare
<:sig_item< declare $list:lsi$ end >>
MLast.SgDcl loc (Ploc.VaVal lsi)

<:sig_item< declare $_list:lsi$ end >>
MLast.SgDcl loc lsi
- directive
<:sig_item< # $lid:s$ >>
MLast.SgDir loc (Ploc.VaVal s) (Ploc.VaVal None)

<:sig_item< # $lid:s$ $e$ >>
MLast.SgDir loc (Ploc.VaVal s) (Ploc.VaVal (Some e))

<:sig_item< # $lid:s$ $opt:oe$ >>
MLast.SgDir loc (Ploc.VaVal s) (Ploc.VaVal oe)

<:sig_item< # $lid:s$ $_opt:oe$ >>
MLast.SgDir loc (Ploc.VaVal s) oe

<:sig_item< # $_lid:s$ >>
MLast.SgDir loc s (Ploc.VaVal None)

<:sig_item< # $_lid:s$ $e$ >>
MLast.SgDir loc s (Ploc.VaVal (Some e))

<:sig_item< # $_lid:s$ $opt:oe$ >>
MLast.SgDir loc s (Ploc.VaVal oe)

<:sig_item< # $_lid:s$ $_opt:oe$ >>
MLast.SgDir loc s oe
- exception
<:sig_item< exception $s$ >>
MLast.SgExc loc (Ploc.VaVal s) (Ploc.VaVal [])

<:sig_item< exception $s$ of $list:lt$ >>
MLast.SgExc loc (Ploc.VaVal s) (Ploc.VaVal lt)

<:sig_item< exception $s$ of $_list:lt$ >>
MLast.SgExc loc (Ploc.VaVal s) lt

<:sig_item< exception $_:s$ >>
MLast.SgExc loc s (Ploc.VaVal [])

<:sig_item< exception $_:s$ of $list:lt$ >>
MLast.SgExc loc s (Ploc.VaVal lt)

<:sig_item< exception $_:s$ of $_list:lt$ >>
MLast.SgExc loc s lt
- external
<:sig_item< external $s$ : $t$ = $list:ls$ >>
MLast.SgExt loc (Ploc.VaVal s) t (Ploc.VaVal ls)

<:sig_item< external $s$ : $t$ = $_list:ls$ >>
MLast.SgExt loc (Ploc.VaVal s) t ls

<:sig_item< external $_:s$ : $t$ = $list:ls$ >>
MLast.SgExt loc s t (Ploc.VaVal ls)

<:sig_item< external $_:s$ : $t$ = $_list:ls$ >>
MLast.SgExt loc s t ls
- include
<:sig_item< include $mt$ >>
MLast.SgInc loc mt
- module rec
<:sig_item< module rec $list:lsmt$ >>
MLast.SgMod loc (Ploc.VaVal True) (Ploc.VaVal lsmt)

<:sig_item< module rec $_list:lsmt$ >>
MLast.SgMod loc (Ploc.VaVal True) lsmt
- module non rec
<:sig_item< module $list:lsmt$ >>
MLast.SgMod loc (Ploc.VaVal False) (Ploc.VaVal lsmt)

<:sig_item< module $_list:lsmt$ >>
MLast.SgMod loc (Ploc.VaVal False) lsmt
- module
<:sig_item< module $flag:b$ $list:lsmt$ >>
MLast.SgMod loc (Ploc.VaVal b) (Ploc.VaVal lsmt)

<:sig_item< module $flag:b$ $_list:lsmt$ >>
MLast.SgMod loc (Ploc.VaVal b) lsmt

<:sig_item< module $_flag:b$ $list:lsmt$ >>
MLast.SgMod loc b (Ploc.VaVal lsmt)

<:sig_item< module $_flag:b$ $_list:lsmt$ >>
MLast.SgMod loc b lsmt
- module type
<:sig_item< module type $s$ = $mt$ >>
MLast.SgMty loc (Ploc.VaVal s) mt

<:sig_item< module type $_:s$ = $mt$ >>
MLast.SgMty loc s mt
- open
<:sig_item< open $list:ls$ >>
MLast.SgOpn loc (Ploc.VaVal ls)

<:sig_item< open $_list:ls$ >>
MLast.SgOpn loc ls
- type declaration
<:sig_item< type $list:ltd$ >>
MLast.SgTyp loc (Ploc.VaVal ltd)

<:sig_item< type $_list:ltd$ >>
MLast.SgTyp loc ltd
- ... internal use ... (1)
<:sig_item< # $str:s$ $list:lsil$ >>
MLast.SgUse loc (Ploc.VaVal s) (Ploc.VaVal lsil)

<:sig_item< # $str:s$ $_list:lsil$ >>
MLast.SgUse loc (Ploc.VaVal s) lsil

<:sig_item< # $_str:s$ $list:lsil$ >>
MLast.SgUse loc s (Ploc.VaVal lsil)

<:sig_item< # $_str:s$ $_list:lsil$ >>
MLast.SgUse loc s lsil
- value
<:sig_item< value $s$ : $t$ >>
MLast.SgVal loc (Ploc.VaVal s) t

<:sig_item< value $_:s$ : $t$ >>
MLast.SgVal loc s t
- extra node (2)
... no representation ...
MLast.SgXtr loc s ot
(1) Same remark as for "str_item" above.
(2) Extra node internally used by the quotation kit "q_ast.cmo" to build antiquotations of signature items.

module_expr

- access
<:module_expr< $me1$ . $me2$ >>
MLast.MeAcc loc me1 me2
- application
<:module_expr< $me1$ $me2$ >>
MLast.MeApp loc me1 me2
- functor
<:module_expr< functor ($s$ : $mt$) -> $me$ >>
MLast.MeFun loc (Ploc.VaVal s) mt me

<:module_expr< functor ($_:s$ : $mt$) -> $me$ >>
MLast.MeFun loc s mt me
- struct
<:module_expr< struct $list:lsi$ end >>
MLast.MeStr loc (Ploc.VaVal lsi)

<:module_expr< struct $_list:lsi$ end >>
MLast.MeStr loc lsi
- module type constraint
<:module_expr< ($me$ : $mt$) >>
MLast.MeTyc loc me mt
- uppercase identifier
<:module_expr< $uid:s$ >>
MLast.MeUid loc (Ploc.VaVal s)

<:module_expr< $_uid:s$ >>
MLast.MeUid loc s
- module unpacking
<:module_expr< (value $e$) >>
MLast.MeUnp loc e None

<:module_expr< (value $e$ : $mt$) >>
MLast.MeUnp loc e (Some mt)
- extra node (1)
... no representation ...
MLast.MeXtr loc s ot
(1) Extra node internally used by the quotation kit "q_ast.cmo" to build antiquotations of module expressions.

module_type

- access
<:module_type< $mt1$ . $mt2$ >>
MLast.MtAcc loc mt1 mt2
- application
<:module_type< $mt1$ $mt2$ >>
MLast.MtApp loc mt1 mt2
- functor
<:module_type< functor ($s$ : $mt1$) -> $mt2$ >>
MLast.MtFun loc (Ploc.VaVal s) mt1 mt2

<:module_type< functor ($_:s$ : $mt1$) -> $mt2$ >>
MLast.MtFun loc s mt1 mt2
- lowercase identifier
<:module_type< $lid:s$ >>
MLast.MtLid loc (Ploc.VaVal s)

<:module_type< $_lid:s$ >>
MLast.MtLid loc s
- abstract
<:module_type< ' $s$ >>
MLast.MtQuo loc (Ploc.VaVal s)

<:module_type< ' $_:s$ >>
MLast.MtQuo loc s
- signature
<:module_type< sig $list:lsi$ end >>
MLast.MtSig loc (Ploc.VaVal lsi)

<:module_type< sig $_list:lsi$ end >>
MLast.MtSig loc lsi
- of module expression
<:module_type< module type of $me$ >>
MLast.MtTyo loc me
- uppercase identifier
<:module_type< $uid:s$ >>
MLast.MtUid loc (Ploc.VaVal s)

<:module_type< $_uid:s$ >>
MLast.MtUid loc s
- with construction
<:module_type< $mt$ with $list:lwc$ >>
MLast.MtWit loc mt (Ploc.VaVal lwc)

<:module_type< $mt$ with $_list:lwc$ >>
MLast.MtWit loc mt lwc
- extra node (1)
... no representation ...
MLast.MtXtr loc s ot
(1) Extra node internally used by the quotation kit "q_ast.cmo" to build antiquotations of module types.

classes...

class_expr

- application
<:class_expr< $ce$ $e$ >>
MLast.CeApp loc ce e
- constructor
<:class_expr< [ $list:lt$ ] $list:ls$ >>
MLast.CeCon loc (Ploc.VaVal ls) (Ploc.VaVal lt)

<:class_expr< [ $_list:lt$ ] $list:ls$ >>
MLast.CeCon loc (Ploc.VaVal ls) lt

<:class_expr< [ $list:lt$ ] $_list:ls$ >>
MLast.CeCon loc ls (Ploc.VaVal lt)

<:class_expr< [ $_list:lt$ ] $_list:ls$ >>
MLast.CeCon loc ls lt
- function
<:class_expr< fun $p$ -> $ce$ >>
MLast.CeFun loc p ce
- let rec
<:class_expr< let rec $list:lpe$ in $ce$ >>
MLast.CeLet loc (Ploc.VaVal True) (Ploc.VaVal lpe) ce

<:class_expr< let rec $_list:lpe$ in $ce$ >>
MLast.CeLet loc (Ploc.VaVal True) lpe ce
- let non rec
<:class_expr< let $list:lpe$ in $ce$ >>
MLast.CeLet loc (Ploc.VaVal False) (Ploc.VaVal lpe) ce

<:class_expr< let $_list:lpe$ in $ce$ >>
MLast.CeLet loc (Ploc.VaVal False) lpe ce
- let
<:class_expr< let $flag:b$ $list:lpe$ in $ce$ >>
MLast.CeLet loc (Ploc.VaVal b) (Ploc.VaVal lpe) ce

<:class_expr< let $flag:b$ $_list:lpe$ in $ce$ >>
MLast.CeLet loc (Ploc.VaVal b) lpe ce

<:class_expr< let $_flag:b$ $list:lpe$ in $ce$ >>
MLast.CeLet loc b (Ploc.VaVal lpe) ce

<:class_expr< let $_flag:b$ $_list:lpe$ in $ce$ >>
MLast.CeLet loc b lpe ce
- object
<:class_expr< object $list:lcsi$ end >>
MLast.CeStr loc (Ploc.VaVal None) (Ploc.VaVal lcsi)

<:class_expr< object $_list:lcsi$ end >>
MLast.CeStr loc (Ploc.VaVal None) lcsi

<:class_expr< object ($p$) $list:lcsi$ end >>
MLast.CeStr loc (Ploc.VaVal (Some p)) (Ploc.VaVal lcsi)

<:class_expr< object ($p$) $_list:lcsi$ end >>
MLast.CeStr loc (Ploc.VaVal (Some p)) lcsi

<:class_expr< object $opt:op$ $list:lcsi$ end >>
MLast.CeStr loc (Ploc.VaVal op) (Ploc.VaVal lcsi)

<:class_expr< object $opt:op$ $_list:lcsi$ end >>
MLast.CeStr loc (Ploc.VaVal op) lcsi

<:class_expr< object $_opt:op$ $list:lcsi$ end >>
MLast.CeStr loc op (Ploc.VaVal lcsi)

<:class_expr< object $_opt:op$ $_list:lcsi$ end >>
MLast.CeStr loc op lcsi
- class type constraint
<:class_expr< ($ce$ : $ct$) >>
MLast.CeTyc loc ce ct

class_type

- access
<:class_type< $ct1$ . $ct2$ >>
MLast.CtAcc loc ct1 ct2
- application
<:class_type< $ct1$ $ct2$ >>
MLast.CtApp loc ct1 ct2
- constructor
<:class_type< $ct$ [ $list:lt$ ] >>
MLast.CtCon loc ct (Ploc.VaVal lt)

<:class_type< $ct$ [ $_list:lt$ ] >>
MLast.CtCon loc ct lt
- arrow
<:class_type< [ $t$ ] -> $ct$ >>
MLast.CtFun loc t ct
- identifier
<:class_type< $id:s$ >>
MLast.CtIde loc (Ploc.VaVal s)

<:class_type< $_id:s$ >>
MLast.CtIde loc s
- object
<:class_type< object $list:lcsi$ end >>
MLast.CtSig loc (Ploc.VaVal None) (Ploc.VaVal lcsi)

<:class_type< object $_list:lcsi$ end >>
MLast.CtSig loc (Ploc.VaVal None) lcsi

<:class_type< object ($t$) $list:lcsi$ end >>
MLast.CtSig loc (Ploc.VaVal (Some t)) (Ploc.VaVal lcsi)

<:class_type< object ($t$) $_list:lcsi$ end >>
MLast.CtSig loc (Ploc.VaVal (Some t)) lcsi

<:class_type< object $opt:ot$ $list:lcsi$ end >>
MLast.CtSig loc (Ploc.VaVal ot) (Ploc.VaVal lcsi)

<:class_type< object $opt:ot$ $_list:lcsi$ end >>
MLast.CtSig loc (Ploc.VaVal ot) lcsi

<:class_type< object $_opt:ot$ $list:lcsi$ end >>
MLast.CtSig loc ot (Ploc.VaVal lcsi)

<:class_type< object $_opt:ot$ $_list:lcsi$ end >>
MLast.CtSig loc ot lcsi

class_str_item

- type constraint
<:class_str_item< type $t1$ = $t2$ >>
MLast.CrCtr loc t1 t2
- declaration list
<:class_str_item< declare $list:lcsi$ end >>
MLast.CrDcl loc (Ploc.VaVal lcsi)

<:class_str_item< declare $_list:lcsi$ end >>
MLast.CrDcl loc lcsi
- inheritance
<:class_str_item< inherit $ce$ >>
MLast.CrInh loc ce (Ploc.VaVal None)

<:class_str_item< inherit $ce$ $opt:Some s$ >>
MLast.CrInh loc ce (Ploc.VaVal (Some s))

<:class_str_item< inherit $ce$ $opt:os$ >>
MLast.CrInh loc ce (Ploc.VaVal os)

<:class_str_item< inherit $ce$ $_opt:os$ >>
MLast.CrInh loc ce os
- initialization
<:class_str_item< initializer $e$ >>
MLast.CrIni loc e
- method
<:class_str_item< method! private $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method! private $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method! private $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method! private $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal True) (Ploc.VaVal s) ot e

<:class_str_item< method! private $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal True) s (Ploc.VaVal None) e

<:class_str_item< method! private $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal True) s (Ploc.VaVal (Some t)) e

<:class_str_item< method! private $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal True) s (Ploc.VaVal ot) e

<:class_str_item< method! private $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal True) s ot e

<:class_str_item< method! $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method! $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method! $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method! $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal False) (Ploc.VaVal s) ot e

<:class_str_item< method! $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal False) s (Ploc.VaVal None) e

<:class_str_item< method! $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal False) s (Ploc.VaVal (Some t)) e

<:class_str_item< method! $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal False) s (Ploc.VaVal ot) e

<:class_str_item< method! $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal False) s ot e

<:class_str_item< method! $priv:b2$ $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method! $priv:b2$ $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method! $priv:b2$ $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method! $priv:b2$ $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal b2) (Ploc.VaVal s) ot e

<:class_str_item< method! $priv:b2$ $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal b2) s (Ploc.VaVal None) e

<:class_str_item< method! $priv:b2$ $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal b2) s (Ploc.VaVal (Some t)) e

<:class_str_item< method! $priv:b2$ $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal b2) s (Ploc.VaVal ot) e

<:class_str_item< method! $priv:b2$ $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) (Ploc.VaVal b2) s ot e

<:class_str_item< method! $_priv:b2$ $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) b2 (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method! $_priv:b2$ $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) b2 (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method! $_priv:b2$ $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) b2 (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method! $_priv:b2$ $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) b2 (Ploc.VaVal s) ot e

<:class_str_item< method! $_priv:b2$ $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) b2 s (Ploc.VaVal None) e

<:class_str_item< method! $_priv:b2$ $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) b2 s (Ploc.VaVal (Some t)) e

<:class_str_item< method! $_priv:b2$ $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) b2 s (Ploc.VaVal ot) e

<:class_str_item< method! $_priv:b2$ $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal True) b2 s ot e

<:class_str_item< method private $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method private $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method private $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method private $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal True) (Ploc.VaVal s) ot e

<:class_str_item< method private $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal True) s (Ploc.VaVal None) e

<:class_str_item< method private $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal True) s (Ploc.VaVal (Some t)) e

<:class_str_item< method private $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal True) s (Ploc.VaVal ot) e

<:class_str_item< method private $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal True) s ot e

<:class_str_item< method $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal False) (Ploc.VaVal s) ot e

<:class_str_item< method $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal False) s (Ploc.VaVal None) e

<:class_str_item< method $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal False) s (Ploc.VaVal (Some t)) e

<:class_str_item< method $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal False) s (Ploc.VaVal ot) e

<:class_str_item< method $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal False) s ot e

<:class_str_item< method $priv:b2$ $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method $priv:b2$ $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method $priv:b2$ $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method $priv:b2$ $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal b2) (Ploc.VaVal s) ot e

<:class_str_item< method $priv:b2$ $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal b2) s (Ploc.VaVal None) e

<:class_str_item< method $priv:b2$ $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal b2) s (Ploc.VaVal (Some t)) e

<:class_str_item< method $priv:b2$ $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal b2) s (Ploc.VaVal ot) e

<:class_str_item< method $priv:b2$ $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) (Ploc.VaVal b2) s ot e

<:class_str_item< method $_priv:b2$ $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) b2 (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method $_priv:b2$ $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) b2 (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method $_priv:b2$ $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) b2 (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method $_priv:b2$ $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) b2 (Ploc.VaVal s) ot e

<:class_str_item< method $_priv:b2$ $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) b2 s (Ploc.VaVal None) e

<:class_str_item< method $_priv:b2$ $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) b2 s (Ploc.VaVal (Some t)) e

<:class_str_item< method $_priv:b2$ $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) b2 s (Ploc.VaVal ot) e

<:class_str_item< method $_priv:b2$ $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal False) b2 s ot e

<:class_str_item< method $!:b1$ private $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method $!:b1$ private $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method $!:b1$ private $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method $!:b1$ private $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal True) (Ploc.VaVal s) ot e

<:class_str_item< method $!:b1$ private $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal True) s (Ploc.VaVal None) e

<:class_str_item< method $!:b1$ private $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal True) s (Ploc.VaVal (Some t)) e

<:class_str_item< method $!:b1$ private $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal True) s (Ploc.VaVal ot) e

<:class_str_item< method $!:b1$ private $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal True) s ot e

<:class_str_item< method $!:b1$ $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method $!:b1$ $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method $!:b1$ $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method $!:b1$ $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal False) (Ploc.VaVal s) ot e

<:class_str_item< method $!:b1$ $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal False) s (Ploc.VaVal None) e

<:class_str_item< method $!:b1$ $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal False) s (Ploc.VaVal (Some t)) e

<:class_str_item< method $!:b1$ $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal False) s (Ploc.VaVal ot) e

<:class_str_item< method $!:b1$ $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal False) s ot e

<:class_str_item< method $!:b1$ $priv:b2$ $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method $!:b1$ $priv:b2$ $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method $!:b1$ $priv:b2$ $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method $!:b1$ $priv:b2$ $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal b2) (Ploc.VaVal s) ot e

<:class_str_item< method $!:b1$ $priv:b2$ $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal b2) s (Ploc.VaVal None) e

<:class_str_item< method $!:b1$ $priv:b2$ $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal b2) s (Ploc.VaVal (Some t)) e

<:class_str_item< method $!:b1$ $priv:b2$ $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal b2) s (Ploc.VaVal ot) e

<:class_str_item< method $!:b1$ $priv:b2$ $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) (Ploc.VaVal b2) s ot e

<:class_str_item< method $!:b1$ $_priv:b2$ $lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) b2 (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method $!:b1$ $_priv:b2$ $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) b2 (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method $!:b1$ $_priv:b2$ $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) b2 (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method $!:b1$ $_priv:b2$ $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) b2 (Ploc.VaVal s) ot e

<:class_str_item< method $!:b1$ $_priv:b2$ $_lid:s$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) b2 s (Ploc.VaVal None) e

<:class_str_item< method $!:b1$ $_priv:b2$ $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) b2 s (Ploc.VaVal (Some t)) e

<:class_str_item< method $!:b1$ $_priv:b2$ $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) b2 s (Ploc.VaVal ot) e

<:class_str_item< method $!:b1$ $_priv:b2$ $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc (Ploc.VaVal b1) b2 s ot e

<:class_str_item< method $_!:b1$ private $lid:s$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method $_!:b1$ private $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method $_!:b1$ private $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal True) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method $_!:b1$ private $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal True) (Ploc.VaVal s) ot e

<:class_str_item< method $_!:b1$ private $_lid:s$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal True) s (Ploc.VaVal None) e

<:class_str_item< method $_!:b1$ private $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal True) s (Ploc.VaVal (Some t)) e

<:class_str_item< method $_!:b1$ private $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal True) s (Ploc.VaVal ot) e

<:class_str_item< method $_!:b1$ private $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal True) s ot e

<:class_str_item< method $_!:b1$ $lid:s$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method $_!:b1$ $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method $_!:b1$ $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal False) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method $_!:b1$ $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal False) (Ploc.VaVal s) ot e

<:class_str_item< method $_!:b1$ $_lid:s$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal False) s (Ploc.VaVal None) e

<:class_str_item< method $_!:b1$ $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal False) s (Ploc.VaVal (Some t)) e

<:class_str_item< method $_!:b1$ $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal False) s (Ploc.VaVal ot) e

<:class_str_item< method $_!:b1$ $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal False) s ot e

<:class_str_item< method $_!:b1$ $priv:b2$ $lid:s$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method $_!:b1$ $priv:b2$ $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method $_!:b1$ $priv:b2$ $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal b2) (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method $_!:b1$ $priv:b2$ $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal b2) (Ploc.VaVal s) ot e

<:class_str_item< method $_!:b1$ $priv:b2$ $_lid:s$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal b2) s (Ploc.VaVal None) e

<:class_str_item< method $_!:b1$ $priv:b2$ $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal b2) s (Ploc.VaVal (Some t)) e

<:class_str_item< method $_!:b1$ $priv:b2$ $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal b2) s (Ploc.VaVal ot) e

<:class_str_item< method $_!:b1$ $priv:b2$ $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc b1 (Ploc.VaVal b2) s ot e

<:class_str_item< method $_!:b1$ $_priv:b2$ $lid:s$ = $e$ >>
MLast.CrMth loc b1 b2 (Ploc.VaVal s) (Ploc.VaVal None) e

<:class_str_item< method $_!:b1$ $_priv:b2$ $lid:s$ : $t$ = $e$ >>
MLast.CrMth loc b1 b2 (Ploc.VaVal s) (Ploc.VaVal (Some t)) e

<:class_str_item< method $_!:b1$ $_priv:b2$ $lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc b1 b2 (Ploc.VaVal s) (Ploc.VaVal ot) e

<:class_str_item< method $_!:b1$ $_priv:b2$ $lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc b1 b2 (Ploc.VaVal s) ot e

<:class_str_item< method $_!:b1$ $_priv:b2$ $_lid:s$ = $e$ >>
MLast.CrMth loc b1 b2 s (Ploc.VaVal None) e

<:class_str_item< method $_!:b1$ $_priv:b2$ $_lid:s$ : $t$ = $e$ >>
MLast.CrMth loc b1 b2 s (Ploc.VaVal (Some t)) e

<:class_str_item< method $_!:b1$ $_priv:b2$ $_lid:s$ $opt:ot$ = $e$ >>
MLast.CrMth loc b1 b2 s (Ploc.VaVal ot) e

<:class_str_item< method $_!:b1$ $_priv:b2$ $_lid:s$ $_opt:ot$ = $e$ >>
MLast.CrMth loc b1 b2 s ot e
- value
<:class_str_item< value! mutable $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal True) (Ploc.VaVal True) (Ploc.VaVal s) e

<:class_str_item< value! mutable $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal True) (Ploc.VaVal True) s e

<:class_str_item< value! $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal True) (Ploc.VaVal False) (Ploc.VaVal s) e

<:class_str_item< value! $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal True) (Ploc.VaVal False) s e

<:class_str_item< value! $flag:b2$ $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal True) (Ploc.VaVal b2) (Ploc.VaVal s) e

<:class_str_item< value! $flag:b2$ $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal True) (Ploc.VaVal b2) s e

<:class_str_item< value! $_flag:b2$ $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal True) b2 (Ploc.VaVal s) e

<:class_str_item< value! $_flag:b2$ $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal True) b2 s e

<:class_str_item< value mutable $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal False) (Ploc.VaVal True) (Ploc.VaVal s) e

<:class_str_item< value mutable $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal False) (Ploc.VaVal True) s e

<:class_str_item< value $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal False) (Ploc.VaVal False) (Ploc.VaVal s) e

<:class_str_item< value $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal False) (Ploc.VaVal False) s e

<:class_str_item< value $flag:b2$ $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal False) (Ploc.VaVal b2) (Ploc.VaVal s) e

<:class_str_item< value $flag:b2$ $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal False) (Ploc.VaVal b2) s e

<:class_str_item< value $_flag:b2$ $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal False) b2 (Ploc.VaVal s) e

<:class_str_item< value $_flag:b2$ $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal False) b2 s e

<:class_str_item< value $!:b1$ mutable $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal b1) (Ploc.VaVal True) (Ploc.VaVal s) e

<:class_str_item< value $!:b1$ mutable $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal b1) (Ploc.VaVal True) s e

<:class_str_item< value $!:b1$ $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal b1) (Ploc.VaVal False) (Ploc.VaVal s) e

<:class_str_item< value $!:b1$ $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal b1) (Ploc.VaVal False) s e

<:class_str_item< value $!:b1$ $flag:b2$ $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal b1) (Ploc.VaVal b2) (Ploc.VaVal s) e

<:class_str_item< value $!:b1$ $flag:b2$ $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal b1) (Ploc.VaVal b2) s e

<:class_str_item< value $!:b1$ $_flag:b2$ $lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal b1) b2 (Ploc.VaVal s) e

<:class_str_item< value $!:b1$ $_flag:b2$ $_lid:s$ = $e$ >>
MLast.CrVal loc (Ploc.VaVal b1) b2 s e

<:class_str_item< value $_!:b1$ mutable $lid:s$ = $e$ >>
MLast.CrVal loc b1 (Ploc.VaVal True) (Ploc.VaVal s) e

<:class_str_item< value $_!:b1$ mutable $_lid:s$ = $e$ >>
MLast.CrVal loc b1 (Ploc.VaVal True) s e

<:class_str_item< value $_!:b1$ $lid:s$ = $e$ >>
MLast.CrVal loc b1 (Ploc.VaVal False) (Ploc.VaVal s) e

<:class_str_item< value $_!:b1$ $_lid:s$ = $e$ >>
MLast.CrVal loc b1 (Ploc.VaVal False) s e

<:class_str_item< value $_!:b1$ $flag:b2$ $lid:s$ = $e$ >>
MLast.CrVal loc b1 (Ploc.VaVal b2) (Ploc.VaVal s) e

<:class_str_item< value $_!:b1$ $flag:b2$ $_lid:s$ = $e$ >>
MLast.CrVal loc b1 (Ploc.VaVal b2) s e

<:class_str_item< value $_!:b1$ $_flag:b2$ $lid:s$ = $e$ >>
MLast.CrVal loc b1 b2 (Ploc.VaVal s) e

<:class_str_item< value $_!:b1$ $_flag:b2$ $_lid:s$ = $e$ >>
MLast.CrVal loc b1 b2 s e
- virtual value
<:class_str_item< value virtual mutable $lid:s$ : $t$ >>
MLast.CrVav loc (Ploc.VaVal True) (Ploc.VaVal s) t

<:class_str_item< value virtual mutable $_lid:s$ : $t$ >>
MLast.CrVav loc (Ploc.VaVal True) s t

<:class_str_item< value virtual $lid:s$ : $t$ >>
MLast.CrVav loc (Ploc.VaVal False) (Ploc.VaVal s) t

<:class_str_item< value virtual $_lid:s$ : $t$ >>
MLast.CrVav loc (Ploc.VaVal False) s t

<:class_str_item< value virtual $flag:b$ $lid:s$ : $t$ >>
MLast.CrVav loc (Ploc.VaVal b) (Ploc.VaVal s) t

<:class_str_item< value virtual $flag:b$ $_lid:s$ : $t$ >>
MLast.CrVav loc (Ploc.VaVal b) s t

<:class_str_item< value virtual $_flag:b$ $lid:s$ : $t$ >>
MLast.CrVav loc b (Ploc.VaVal s) t

<:class_str_item< value virtual $_flag:b$ $_lid:s$ : $t$ >>
MLast.CrVav loc b s t
- virtual method
<:class_str_item< method virtual private $lid:s$ : $t$ >>
MLast.CrVir loc (Ploc.VaVal True) (Ploc.VaVal s) t

<:class_str_item< method virtual private $_lid:s$ : $t$ >>
MLast.CrVir loc (Ploc.VaVal True) s t

<:class_str_item< method virtual $lid:s$ : $t$ >>
MLast.CrVir loc (Ploc.VaVal False) (Ploc.VaVal s) t

<:class_str_item< method virtual $_lid:s$ : $t$ >>
MLast.CrVir loc (Ploc.VaVal False) s t

<:class_str_item< method virtual $flag:b$ $lid:s$ : $t$ >>
MLast.CrVir loc (Ploc.VaVal b) (Ploc.VaVal s) t

<:class_str_item< method virtual $flag:b$ $_lid:s$ : $t$ >>
MLast.CrVir loc (Ploc.VaVal b) s t

<:class_str_item< method virtual $_flag:b$ $lid:s$ : $t$ >>
MLast.CrVir loc b (Ploc.VaVal s) t

<:class_str_item< method virtual $_flag:b$ $_lid:s$ : $t$ >>
MLast.CrVir loc b s t

class_sig_item

- type constraint
<:class_sig_item< type $t1$ = $t2$ >>
MLast.CgCtr loc t1 t2
- declare
<:class_sig_item< declare $list:lcsi$ end >>
MLast.CgDcl loc (Ploc.VaVal lcsi)

<:class_sig_item< declare $_list:lcsi$ end >>
MLast.CgDcl loc lcsi
- inheritance
<:class_sig_item< inherit $ct$ >>
MLast.CgInh loc ct
- method
<:class_sig_item< method private $lid:s$ : $t$ >>
MLast.CgMth loc (Ploc.VaVal True) (Ploc.VaVal s) t

<:class_sig_item< method private $_lid:s$ : $t$ >>
MLast.CgMth loc (Ploc.VaVal True) s t

<:class_sig_item< method $lid:s$ : $t$ >>
MLast.CgMth loc (Ploc.VaVal False) (Ploc.VaVal s) t

<:class_sig_item< method $_lid:s$ : $t$ >>
MLast.CgMth loc (Ploc.VaVal False) s t

<:class_sig_item< method $flag:b$ $lid:s$ : $t$ >>
MLast.CgMth loc (Ploc.VaVal b) (Ploc.VaVal s) t

<:class_sig_item< method $flag:b$ $_lid:s$ : $t$ >>
MLast.CgMth loc (Ploc.VaVal b) s t

<:class_sig_item< method $_flag:b$ $lid:s$ : $t$ >>
MLast.CgMth loc b (Ploc.VaVal s) t

<:class_sig_item< method $_flag:b$ $_lid:s$ : $t$ >>
MLast.CgMth loc b s t
- value
<:class_sig_item< value mutable $lid:s$ : $t$ >>
MLast.CgVal loc (Ploc.VaVal True) (Ploc.VaVal s) t

<:class_sig_item< value mutable $_lid:s$ : $t$ >>
MLast.CgVal loc (Ploc.VaVal True) s t

<:class_sig_item< value $lid:s$ : $t$ >>
MLast.CgVal loc (Ploc.VaVal False) (Ploc.VaVal s) t

<:class_sig_item< value $_lid:s$ : $t$ >>
MLast.CgVal loc (Ploc.VaVal False) s t

<:class_sig_item< value $flag:b$ $lid:s$ : $t$ >>
MLast.CgVal loc (Ploc.VaVal b) (Ploc.VaVal s) t

<:class_sig_item< value $flag:b$ $_lid:s$ : $t$ >>
MLast.CgVal loc (Ploc.VaVal b) s t

<:class_sig_item< value $_flag:b$ $lid:s$ : $t$ >>
MLast.CgVal loc b (Ploc.VaVal s) t

<:class_sig_item< value $_flag:b$ $_lid:s$ : $t$ >>
MLast.CgVal loc b s t
- virtual method
<:class_sig_item< method virtual private $lid:s$ : $t$ >>
MLast.CgVir loc (Ploc.VaVal True) (Ploc.VaVal s) t

<:class_sig_item< method virtual private $_lid:s$ : $t$ >>
MLast.CgVir loc (Ploc.VaVal True) s t

<:class_sig_item< method virtual $lid:s$ : $t$ >>
MLast.CgVir loc (Ploc.VaVal False) (Ploc.VaVal s) t

<:class_sig_item< method virtual $_lid:s$ : $t$ >>
MLast.CgVir loc (Ploc.VaVal False) s t

<:class_sig_item< method virtual $flag:b$ $lid:s$ : $t$ >>
MLast.CgVir loc (Ploc.VaVal b) (Ploc.VaVal s) t

<:class_sig_item< method virtual $flag:b$ $_lid:s$ : $t$ >>
MLast.CgVir loc (Ploc.VaVal b) s t

<:class_sig_item< method virtual $_flag:b$ $lid:s$ : $t$ >>
MLast.CgVir loc b (Ploc.VaVal s) t

<:class_sig_item< method virtual $_flag:b$ $_lid:s$ : $t$ >>
MLast.CgVir loc b s t

other

type_decl

What is after 'type' or 'and' in a type declaration.

The type "type_decl" is a record type corresponding to a type declaration. Its definition is:

  type type_decl =
    { tdNam : (loc * Ploc.vaval string);
      tdPrm : Ploc.vala (list type_var);
      tdPrv : Ploc.vala bool;
      tdDef : ctyp;
      tdCon : Ploc.vala (list (ctyp * ctyp)) }
  ;

The field "tdNam" is the type identifier (together with its location in the source).

The field "tdPrm" is the list of its possible parameters.

The field "tdPrv" tells if the type is private or not.

The field "tdDef" is the definition of the type.

The field "tdCon" is the possible list of type constraints.

 
<:type_decl< $tp:ls$ $list:ltv$ = private $t$ $list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal True; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $tp:ls$ $list:ltv$ = private $t$ $_list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal True; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $tp:ls$ $list:ltv$ = $t$ $list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal False; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $tp:ls$ $list:ltv$ = $t$ $_list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal False; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $tp:ls$ $list:ltv$ = $priv:b$ $t$ $list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal b; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $tp:ls$ $list:ltv$ = $priv:b$ $t$ $_list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal b; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $tp:ls$ $list:ltv$ = $_priv:b$ $t$ $list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = b; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $tp:ls$ $list:ltv$ = $_priv:b$ $t$ $_list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = b; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $tp:ls$ $_list:ltv$ = private $t$ $list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal True; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $tp:ls$ $_list:ltv$ = private $t$ $_list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal True; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $tp:ls$ $_list:ltv$ = $t$ $list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal False; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $tp:ls$ $_list:ltv$ = $t$ $_list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal False; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $tp:ls$ $_list:ltv$ = $priv:b$ $t$ $list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal b; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $tp:ls$ $_list:ltv$ = $priv:b$ $t$ $_list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal b; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $tp:ls$ $_list:ltv$ = $_priv:b$ $t$ $list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = ltv; MLast.tdPrv = b; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $tp:ls$ $_list:ltv$ = $_priv:b$ $t$ $_list:ltt$ >>
{MLast.tdNam = Ploc.VaVal ls; MLast.tdPrm = ltv; MLast.tdPrv = b; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $_tp:ls$ $list:ltv$ = private $t$ $list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal True; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $_tp:ls$ $list:ltv$ = private $t$ $_list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal True; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $_tp:ls$ $list:ltv$ = $t$ $list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal False; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $_tp:ls$ $list:ltv$ = $t$ $_list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal False; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $_tp:ls$ $list:ltv$ = $priv:b$ $t$ $list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal b; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $_tp:ls$ $list:ltv$ = $priv:b$ $t$ $_list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = Ploc.VaVal b; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $_tp:ls$ $list:ltv$ = $_priv:b$ $t$ $list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = b; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $_tp:ls$ $list:ltv$ = $_priv:b$ $t$ $_list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = Ploc.VaVal ltv; MLast.tdPrv = b; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $_tp:ls$ $_list:ltv$ = private $t$ $list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal True; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $_tp:ls$ $_list:ltv$ = private $t$ $_list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal True; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $_tp:ls$ $_list:ltv$ = $t$ $list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal False; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $_tp:ls$ $_list:ltv$ = $t$ $_list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal False; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $_tp:ls$ $_list:ltv$ = $priv:b$ $t$ $list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal b; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $_tp:ls$ $_list:ltv$ = $priv:b$ $t$ $_list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = ltv; MLast.tdPrv = Ploc.VaVal b; MLast.tdDef = t; MLast.tdCon = ltt}

<:type_decl< $_tp:ls$ $_list:ltv$ = $_priv:b$ $t$ $list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = ltv; MLast.tdPrv = b; MLast.tdDef = t; MLast.tdCon = Ploc.VaVal ltt}

<:type_decl< $_tp:ls$ $_list:ltv$ = $_priv:b$ $t$ $_list:ltt$ >>
{MLast.tdNam = ls; MLast.tdPrm = ltv; MLast.tdPrv = b; MLast.tdDef = t; MLast.tdCon = ltt}

with_constr

"With" possibly following a module type.

- with module
<:with_constr< module $list:ls$ = $me$ >>
MLast.WcMod loc (Ploc.VaVal ls) me

<:with_constr< module $_list:ls$ = $me$ >>
MLast.WcMod loc ls me
- with module substitution
<:with_constr< module $list:ls$ := $me$ >>
MLast.WcMos loc (Ploc.VaVal ls) me

<:with_constr< module $_list:ls$ := $me$ >>
MLast.WcMos loc ls me
- with type
<:with_constr< type $list:ls$ $list:ltv$ = private $t$ >>
MLast.WcTyp loc (Ploc.VaVal ls) (Ploc.VaVal ltv) (Ploc.VaVal True) t

<:with_constr< type $list:ls$ $list:ltv$ = $t$ >>
MLast.WcTyp loc (Ploc.VaVal ls) (Ploc.VaVal ltv) (Ploc.VaVal False) t

<:with_constr< type $list:ls$ $list:ltv$ = $flag:b$ $t$ >>
MLast.WcTyp loc (Ploc.VaVal ls) (Ploc.VaVal ltv) (Ploc.VaVal b) t

<:with_constr< type $list:ls$ $list:ltv$ = $_flag:b$ $t$ >>
MLast.WcTyp loc (Ploc.VaVal ls) (Ploc.VaVal ltv) b t

<:with_constr< type $list:ls$ $_list:ltv$ = private $t$ >>
MLast.WcTyp loc (Ploc.VaVal ls) ltv (Ploc.VaVal True) t

<:with_constr< type $list:ls$ $_list:ltv$ = $t$ >>
MLast.WcTyp loc (Ploc.VaVal ls) ltv (Ploc.VaVal False) t

<:with_constr< type $list:ls$ $_list:ltv$ = $flag:b$ $t$ >>
MLast.WcTyp loc (Ploc.VaVal ls) ltv (Ploc.VaVal b) t

<:with_constr< type $list:ls$ $_list:ltv$ = $_flag:b$ $t$ >>
MLast.WcTyp loc (Ploc.VaVal ls) ltv b t

<:with_constr< type $_list:ls$ $list:ltv$ = private $t$ >>
MLast.WcTyp loc ls (Ploc.VaVal ltv) (Ploc.VaVal True) t

<:with_constr< type $_list:ls$ $list:ltv$ = $t$ >>
MLast.WcTyp loc ls (Ploc.VaVal ltv) (Ploc.VaVal False) t

<:with_constr< type $_list:ls$ $list:ltv$ = $flag:b$ $t$ >>
MLast.WcTyp loc ls (Ploc.VaVal ltv) (Ploc.VaVal b) t

<:with_constr< type $_list:ls$ $list:ltv$ = $_flag:b$ $t$ >>
MLast.WcTyp loc ls (Ploc.VaVal ltv) b t

<:with_constr< type $_list:ls$ $_list:ltv$ = private $t$ >>
MLast.WcTyp loc ls ltv (Ploc.VaVal True) t

<:with_constr< type $_list:ls$ $_list:ltv$ = $t$ >>
MLast.WcTyp loc ls ltv (Ploc.VaVal False) t

<:with_constr< type $_list:ls$ $_list:ltv$ = $flag:b$ $t$ >>
MLast.WcTyp loc ls ltv (Ploc.VaVal b) t

<:with_constr< type $_list:ls$ $_list:ltv$ = $_flag:b$ $t$ >>
MLast.WcTyp loc ls ltv b t
- with type substitution
<:with_constr< type $list:ls$ $list:ltv$ := $t$ >>
MLast.WcTys loc (Ploc.VaVal ls) (Ploc.VaVal ltv) t

<:with_constr< type $list:ls$ $_list:ltv$ := $t$ >>
MLast.WcTys loc (Ploc.VaVal ls) ltv t

<:with_constr< type $_list:ls$ $list:ltv$ := $t$ >>
MLast.WcTys loc ls (Ploc.VaVal ltv) t

<:with_constr< type $_list:ls$ $_list:ltv$ := $t$ >>
MLast.WcTys loc ls ltv t

poly_variant

Polymorphic variants.

- constructor
<:poly_variant< `$s$ >>
MLast.PvTag loc (Ploc.VaVal s) (Ploc.VaVal True) (Ploc.VaVal [])

<:poly_variant< `$s$ of & $list:lt$ >>
MLast.PvTag loc (Ploc.VaVal s) (Ploc.VaVal True) (Ploc.VaVal lt)

<:poly_variant< `$s$ of & $_list:lt$ >>
MLast.PvTag loc (Ploc.VaVal s) (Ploc.VaVal True) lt

<:poly_variant< `$s$ of $list:lt$ >>
MLast.PvTag loc (Ploc.VaVal s) (Ploc.VaVal False) (Ploc.VaVal lt)

<:poly_variant< `$s$ of $_list:lt$ >>
MLast.PvTag loc (Ploc.VaVal s) (Ploc.VaVal False) lt

<:poly_variant< `$s$ of $flag:b$ $list:lt$ >>
MLast.PvTag loc (Ploc.VaVal s) (Ploc.VaVal b) (Ploc.VaVal lt)

<:poly_variant< `$s$ of $flag:b$ $_list:lt$ >>
MLast.PvTag loc (Ploc.VaVal s) (Ploc.VaVal b) lt

<:poly_variant< `$s$ of $_flag:b$ $list:lt$ >>
MLast.PvTag loc (Ploc.VaVal s) b (Ploc.VaVal lt)

<:poly_variant< `$s$ of $_flag:b$ $_list:lt$ >>
MLast.PvTag loc (Ploc.VaVal s) b lt

<:poly_variant< `$_:s$ >>
MLast.PvTag loc s (Ploc.VaVal True) (Ploc.VaVal [])

<:poly_variant< `$_:s$ of & $list:lt$ >>
MLast.PvTag loc s (Ploc.VaVal True) (Ploc.VaVal lt)

<:poly_variant< `$_:s$ of & $_list:lt$ >>
MLast.PvTag loc s (Ploc.VaVal True) lt

<:poly_variant< `$_:s$ of $list:lt$ >>
MLast.PvTag loc s (Ploc.VaVal False) (Ploc.VaVal lt)

<:poly_variant< `$_:s$ of $_list:lt$ >>
MLast.PvTag loc s (Ploc.VaVal False) lt

<:poly_variant< `$_:s$ of $flag:b$ $list:lt$ >>
MLast.PvTag loc s (Ploc.VaVal b) (Ploc.VaVal lt)

<:poly_variant< `$_:s$ of $flag:b$ $_list:lt$ >>
MLast.PvTag loc s (Ploc.VaVal b) lt

<:poly_variant< `$_:s$ of $_flag:b$ $list:lt$ >>
MLast.PvTag loc s b (Ploc.VaVal lt)

<:poly_variant< `$_:s$ of $_flag:b$ $_list:lt$ >>
MLast.PvTag loc s b lt
- type
<:poly_variant< $t$ >>
MLast.PvInh loc t

Nodes without quotations

Some types defined in the AST tree module "MLast" don't have an associated quotation. They are:

  • type_var
  • class_infos

type_var

The type "type_var" is defined as:

  type type_var = (Ploc.vala string * (bool * bool));

The first boolean is "True" if the type variable is prefixed by "+" ("plus" sign). The second boolean is "True" if the type variable is prefixed by "-" ("minus" sign).

class_infos

The type "class_infos" is a record type parametrized with a type variable. It is common to:

  • the "class declaration" ("class ..." as structure item), the type variable being "class_expr",
  • the "class description" ("class ..." as signature item), the type variable being "class_type",
  • the "class type declaration" ("class type ..."), the type variable being "class_type".

It is defined as:

  type class_infos 'a =
    { ciLoc : loc;
      ciVir : Ploc.vala bool;
      ciPrm : (loc * Ploc.vala (list type_var));
      ciNam : Ploc.vala string;
      ciExp : 'a }
  ;

The field "ciLoc" is the location of the whole definition.

The field "ciVir" tells whether the type is virtual or not.

The field "ciPrm" is the list of its possible parameters.

The field "ciNam" is the class identifier.

The field "ciExp" is the class definition, depending of its kind.

camlp5-rel8.00.02/doc/htmlp/ast_transi.html000066400000000000000000001345651410261051500205040ustar00rootroot00000000000000 AST - transitional

Syntax tree - transitional mode

This chapter presents the Camlp5 syntax tree when Camlp5 is installed in transitional mode.

Introduction

This syntax tree is defined in the module "MLast" provided by Camlp5. Each node corresponds to a syntactic entity of the corresponding type.

For example, the syntax tree of the statement "if" can be written:

  MLast.ExIfe loc e1 e2 e3

where "loc" is the location in the source, and "e1", "e2" and "e3" are respectively the expression after the "if", the one after the "then" and the one after the "else".

If a program needs to manipulate syntax trees, it can use the nodes defined in the module "MLast". The programmer must know how the concrete syntax is transformed into this abstract syntax.

A simpler solution is to use one of the quotation kit "q_MLast.cmo". It proposes quotations which represent the abstract syntax (the nodes of the module "MLast") into concrete syntax with antiquotations to bind variables inside. The example above can be written:

  <:expr< if $e1$ then $e2$ else $e3$ >>

This representation is very interesting when one wants to manipulate complicated syntax trees. Here is an example taken from the Camlp5 sources themselves:

  <:expr<
    match try Some $f$ with [ Stream.Failure -> None ] with
    [ Some $p$ -> $e$
    | _ -> raise (Stream.Error $e2$) ]
  >>

This example was in a position of a pattern. In abstract syntax, it should have been written:

  MLast.ExMat _
    (MLast.ExTry _ (MLast.ExApp _ (MLast.ExUid _ "Some") f)
       [(MLast.PaAcc _ (MLast.PaUid _ "Stream") (MLast.PaUid _ "Failure"),
         None, MLast.ExUid _ "None")])
    [(MLast.PaApp _ (MLast.PaUid _ "Some") p, None, e);
     (MLast.PaAny _, None,
      MLast.ExApp _ (MLast.ExLid _ "raise")
        (MLast.ExApp _
           (MLast.ExAcc _ (MLast.ExUid _ "Stream") (MLast.ExUid _ "Error"))
           e2))]

Which is less readable and much more complicated to build and update.

Instead of thinking of "a syntax tree", the programmer can think of "a piece of program".

Location

In all syntax tree nodes, the first parameter is the source location of the node.

In expressions

When a quotation is in the context of an expression, the location parameter is "loc" in the node and in all its possible sub-nodes. Example: if we consider the quotation:

  <:sig_item< value foo : int -> bool >>

This quotation, in a context of an expression, is equivalent to:

  MLast.SgVal loc "foo"
    (MLast.TyArr loc (MLast.TyLid loc "int") (MLast.TyLid loc "bool"));

The name "loc" is predefined. However, it is possible to change it, using the argument "-loc" of the Camlp5 shell commands.

Consequently, if there is no variable "loc" defined in the context of the quotation, or if it is not of the correct type, a semantic error occur in the OCaml compiler ("Unbound value loc").

Note that in the extensible grammars, the variable "loc" is bound, in all semantic actions, to the location of the rule.

If the created node has no location, the programmer can define a variable named "loc" equal to "Ploc.dummy".

In patterns

When a quotation is in the context of a pattern, the location parameter of all nodes and possible sub-nodes is set to the wildcard ("_"). The same example above:

  <:sig_item< value foo : int -> bool >>

is equivalent, in a pattern, to:

  MLast.SgVal _ "foo"
    (MLast.TyArr _ (MLast.TyLid _ "int") (MLast.TyLid _ "bool"))

However, it is possible to generate a binding of the variable "loc" on the top node by writing a "colon" before the "less" in the quotation. The same example:

  <:sig_item:< value foo : int -> bool >>

is equivalent to:

  MLast.SgVal loc "foo"
    (MLast.TyArr _ (MLast.TyLid _ "int") (MLast.TyLid _ "bool"))

Antiquotations

The expressions or patterns between dollar ($) characters are called antiquotations. In opposition to quotations which has its own syntax rules, the antiquotation is an area in the syntax of the enclosing context (expression or pattern). See the chapter about quotations.

If a quotation is in the context of an expression, the antiquotation must be an expression. It can be any expression, including function calls. Examples:

  value f e el = <:expr< [$e$ :: $loop False el$] >>;
  value patt_list p pl = <:patt< ( $list:[p::pl]$) >>;

If a quotation is in the context of an pattern, the antiquotation is a pattern. Any pattern is possible, including the wildcard character ("_"). Examples:

   fun [ <:expr< $lid:op$ $_$ $_$ >> -> op ]
   match p with [ <:patt< $_$ | $_$ >> -> Some p ]

Nodes and Quotations

This section describes all nodes defined in the module "MLast" of Camlp5 and how to write them with quotations. Notice that, inside quotations, one is not restricted to these elementary cases, but any complex value can be used, resulting on possibly complex combined nodes.

Variables names give information of their types:

  • e, e1, e2, e3: expr
  • p, p1, p2, p3: patt
  • t, t1, t2, e3: ctyp
  • s: string
  • b: bool
  • me, me1, me2: module_expr
  • mt, mt1, mt2: module_type
  • le: list expr
  • lp: list patt
  • lt: list ctyp
  • ls: list string
  • lse: list (string * expr)
  • lpe: list (patt * expr)
  • lpp: list (patt * patt)
  • lpee: list (patt * option expr * expr)
  • op: option patt
  • lcsi: list class_str_item
  • lcsi: list class_sig_item

expr

Expressions of the language.

Node <:expr< ... >> Comment
ExAcc loc e1 e2 $e1$ . $e2$ access
ExAnt loc e $anti:e$ antiquotation (1)
ExApp loc e1 e2 $e1$ $e2$ application
ExAre loc e1 e2 $e1$ .( $e2$ ) array element
ExArr loc le [| $list:le$ |] array
ExAsr loc e assert $e$ assert
ExAss loc e1 e2 $e1$ := $e2$ assignment
ExBae loc e le $e$ .{ $list:le$ } big array element
ExChr loc s $chr:s$ character constant
ExCoe loc e None t2 ($e$ :> $t2$) coercion
ExCoe loc e (Some t1) t2 ($e$ : $t1$ :> $t2$) coercion
ExFlo loc s $flo:s$ float constant
ExFor loc s e1 e2 True le for $lid:s$ = $e1$ to $e2$ do { $list:le$ } for (increasing)
ExFor loc s e1 e2 False le for $lid:s$ = $e1$ downto $e2$ do { $list:le$ } for (decreasing)
ExFor loc s e1 e2 b le for $lid:s$ = $e1$ $to:b$ $e2$ do { $list:le$ } for
ExFun loc lpee fun [ $list:lpee$ ] function (2)
ExIfe loc e1 e2 e3 if $e1$ then $e2$ else $e3$ if
ExInt loc s1 "" $int:s1$ integer constant
ExInt loc s1 "l" $int32:s1$ integer 32 bits
ExInt loc s1 "L" $int64:s1$ integer 64 bits
ExInt loc s1 "n" $nativeint:s1$ native integer
ExLab loc p None ~{$p$} label
ExLab loc p (Some e) ~{$p$ = $e$} label
ExLab loc p oe ~{$p$ $opt:oe$} label
ExLaz loc e lazy $e$ lazy
ExLet loc True lpe e let rec $list:lpe$ in $e$ let rec
ExLet loc False lpe e let $list:lpe$ in $e$ let not rec
ExLet loc b lpe e let $flag:b$ $list:lpe$ in $e$ let
ExLid loc s $lid:s$ lowercase identifier
ExLmd loc s me e let module $uid:s$ = $me$ in $e$ let module
ExMat loc e lpee match $e$ with [ $list:lpee$ ] match (2)
ExNew loc ls new $list:ls$ new
ExObj loc None lcsi object $list:lcsi$ end object expression
ExObj loc (Some p) lcsi object ($p$) $list:lcsi$ end object expression
ExObj loc op lcsi object $opt:op$ $list:lcsi$ end object expression
ExOlb loc p None ?{$p$} option label
ExOlb loc p (Some e) ?{$p$ = $e$} option label
ExOlb loc p oe ?{$p$ $opt:oe$} option label
ExOvr loc lse {< $list:lse$ >} override
ExPck loc me None (module $me$) module packing
ExPck loc me (Some mt) (module $me$ : $mt$) module packing
ExRec loc lpe None {$list:lpe$} record
ExRec loc lpe (Some e) {($e$) with $list:lpe$} record
ExSeq loc le do { $list:le$ } sequence
ExSnd loc e s $e$ # $s$ method call
ExSte loc e1 e2 $e1$ .[ $e2$ ] string element
ExStr loc s $str:s$ string
ExTry loc e lpee try $e$ with [ $list:lpee$ ] try (2)
ExTup loc le ($list:le$) t-uple
ExTyc loc e t ($e$ : $t$) type constraint
ExUid loc s $uid:s$ uppercase identifier
ExVrn loc s ` $s$ variant
ExWhi loc e le while $e$ do { $list:le$ } while
(1)

Node used in the quotation expanders to tells at conversion to OCaml compiler syntax tree time, that all locations of the sub-tree is correcty located in the quotation. By default, in quotations, the locations of all generated nodes are the location of the whole quotation. This node allows to make an exception to this rule, since we know that the antiquotation belongs to the universe of the enclosing program. See the chapter about quotations and, in particular, its section about antiquotations.

(2)

The variable "lpee" found in "function", "match" and "try" statements correspond to a list of "(patt * option expr * expr)" where the "option expr" is the "when" optionally following the pattern:

  p -> e

is represented by:

  (p, None, e)

and

  p when e1 -> e

is represented by:

  (p, Some e1, e)

patt

Patterns of the language.

Node <:patt< ... >> Comment
PaAcc loc p1 p2 $p1$ . $p2$ access
PaAli loc p1 p2 ($p1$ as $p2$) alias
PaAnt loc p $anti:p$ antiquotation (1)
PaAny loc _ wildcard
PaApp loc p1 p2 $p1$ $p2$ application
PaArr loc lp [| $list:lp$ |] array
PaChr loc s $chr:s$ character
PaFlo loc s $flo:s$ float
PaInt loc s1 "" $int:s1$ integer constant
PaInt loc s1 "l" $int32:s1$ integer 32 bits
PaInt loc s1 "L" $int64:s1$ integer 64 bits
PaInt loc s1 "n" $nativeint:s1$ native integer
PaLab loc p1 None ~{$p1$} label
PaLab loc p1 (Some p2) ~{$p1$ = $p2$} label
PaLab loc p1 op2 ~{$p1$ $opt:op2$} label
PaLaz loc p lazy $p$ lazy
PaLid loc s $lid:s$ lowercase identifier
PaNty loc s (type $lid:s$) new type
PaOlb loc p None ?{$p$} option label
PaOlb loc p (Some e) ?{$p$ = $e$} option label
PaOlb loc p oe ?{$p$ $opt:oe$} option label
PaOrp loc p1 p2 $p1$ | $p2$ or
PaRec loc lpp { $list:lpp$ } record
PaRng loc p1 p2 $p1$ .. $p2$ range
PaStr loc s $str:s$ string
PaTup loc lp ($list:lp$) t-uple
PaTyc loc p t ($p$ : $t$) type constraint
PaTyp loc ls # $list:ls$ type pattern
PaUid loc s $uid:s$ uppercase identifier
PaUnp loc s None (module $uid:s$) module unpacking
PaUnp loc s (Some mt) (module $uid:s$ : $mt$) module unpacking
PaVrn loc s ` $s$ variant
(1) Node used to specify an antiquotation area, like for the equivalent node in expressions. See above.

ctyp

Type expressions of the language.

Node <:ctyp< ... >> Comment
TyAcc loc t1 t2 $t1$ . $t2$ access
TyAli loc t1 t2 $t1$ as $t2$ alias
TyAny loc _ wildcard
TyApp loc t1 t2 $t1$ $t2$ application
TyArr loc t1 t2 $t1$ -> $t2$ arrow
TyCls loc ls # $list:ls$ class
TyLab loc s t ~$s$: $t$ label
TyLid loc s $lid:s$ lowercase identifier
TyMan loc t1 True t2 $t1$ == private $t2$ manifest
TyMan loc t1 False t2 $t1$ == $t2$ manifest
TyMan loc t1 b t2 $t1$ == $priv:b$ $t2$ manifest
TyObj loc lst True < $list:lst$ .. > object
TyObj loc lst False < $list:lst$ > object
TyObj loc lst b < $list:lst$ $flag:b$ > object
TyOlb loc s t ?$s$: $t$ option label
TyPck loc mt (module $mt$) package
TyPol loc ls t ! $list:ls$ . $t$ polymorph
TyQuo loc s '$s$ variable
TyRec loc llsbt { $list:llsbt$ } record
TySum loc llslt [ $list:llslt$ ] sum
TyTup loc lt ( $list:lt$ ) t-uple
TyUid loc s $uid:s$ uppercase identifier
TyVrn loc lpv None [ = $list:lpv$ ] variant
TyVrn loc lpv (Some None) [ > $list:lpv$ ] variant
TyVrn loc lpv (Some (Some [])) [ < $list:lpv$ ] variant
TyVrn loc lpv (Some (Some ls)) [ < $list:lpv$ > $list:ls$ ] variant

modules...

str_item

Structure items, i.e. phrases in a ".ml" file or "struct" elements.

Node <:str_item< ... >> Comment
StCls loc lcice class $list:lcice$ class declaration
StClt loc lcict class type $list:lcict$ class type declaration
StDcl loc lsi declare $list:lsi$ end declare
StDir loc s None # $lid:s$ directive
StDir loc s (Some e) # $lid:s$ $e$ directive
StDir loc s oe # $lid:s$ $opt:oe$ directive
StExc loc s [] [] exception $uid:s$ exception
StExc loc s lt [] exception $uid:s$ of $list:lt$ exception
StExc loc s [] ls exception $uid:s$ = $list:ls$ exception
StExc loc s lt ls exception $uid:s$ of $list:lt$ = $list:ls$ exception
StExp loc e $exp:e$ expression
StExt loc s t ls external $s$ : $t$ = $list:ls$ external
StInc loc me include $me$ include
StMod loc True lsme module rec $list:lsme$ module rec
StMod loc False lsme module $list:lsme$ module non rec
StMod loc b lsme module $flag:b$ $list:lsme$ module
StMty loc s mt module type $s$ = $mt$ module type
StOpn loc ls open $list:ls$ open
StTyp loc ltd type $list:ltd$ type declaration
StUse loc s lsil # $str:s$ $list:lsil$ ... internal use ... (1)
StVal loc True lpe value rec $list:lpe$ value rec
StVal loc False lpe value $list:lpe$ value non rec
StVal loc b lpe value $flag:b$ $list:lpe$ value
(1)

Node internally used to specify a different file name applying to the whole subtree. This is generated by the directive "use" and used when converting to the OCaml syntax tree which needs the file name in its location type.

sig_item

Signature items, i.e. phrases in a ".mli" file or elements inside "sig ... end".

Node <:sig_item< ... >> Comment
SgCls loc lcict class $list:lcict$ class
SgClt loc lcict class type $list:lcict$ class type
SgDcl loc lsi declare $list:lsi$ end declare
SgDir loc s None # $lid:s$ directive
SgDir loc s (Some e) # $lid:s$ $e$ directive
SgDir loc s oe # $lid:s$ $opt:oe$ directive
SgExc loc s [] exception $s$ exception
SgExc loc s lt exception $s$ of $list:lt$ exception
SgExt loc s t ls external $s$ : $t$ = $list:ls$ external
SgInc loc mt include $mt$ include
SgMod loc True lsmt module rec $list:lsmt$ module rec
SgMod loc False lsmt module $list:lsmt$ module non rec
SgMod loc b lsmt module $flag:b$ $list:lsmt$ module
SgMty loc s mt module type $s$ = $mt$ module type
SgOpn loc ls open $list:ls$ open
SgTyp loc ltd type $list:ltd$ type declaration
SgUse loc s lsil # $str:s$ $list:lsil$ ... internal use ... (1)
SgVal loc s t value $s$ : $t$ value
(1)

Same remark as for "str_item" above.

module_expr

Node <:module_expr< ... >> Comment
MeAcc loc me1 me2 $me1$ . $me2$ access
MeApp loc me1 me2 $me1$ $me2$ application
MeFun loc s mt me functor ($s$ : $mt$) -> $me$ functor
MeStr loc lsi struct $list:lsi$ end struct
MeTyc loc me mt ($me$ : $mt$) module type constraint
MeUid loc s $uid:s$ uppercase identifier
MeUnp loc e None (value $e$) module unpacking
MeUnp loc e (Some mt) (value $e$ : $mt$) module unpacking

module_type

Node <:module_type< ... >> Comment
MtAcc loc mt1 mt2 $mt1$ . $mt2$ access
MtApp loc mt1 mt2 $mt1$ $mt2$ application
MtFun loc s mt1 mt2 functor ($s$ : $mt1$) -> $mt2$ functor
MtLid loc s $lid:s$ lowercase identifier
MtQuo loc s ' $s$ abstract
MtSig loc lsi sig $list:lsi$ end signature
MtTyo loc me module type of $me$ of module expression
MtUid loc s $uid:s$ uppercase identifier
MtWit loc mt lwc $mt$ with $list:lwc$ with construction

classes...

class_expr

Node <:class_expr< ... >> Comment
CeApp loc ce e $ce$ $e$ application
CeCon loc ls lt [ $list:lt$ ] $list:ls$ constructor
CeFun loc p ce fun $p$ -> $ce$ function
CeLet loc True lpe ce let rec $list:lpe$ in $ce$ let rec
CeLet loc False lpe ce let $list:lpe$ in $ce$ let non rec
CeLet loc b lpe ce let $flag:b$ $list:lpe$ in $ce$ let
CeStr loc None lcsi object $list:lcsi$ end object
CeStr loc (Some p) lcsi object ($p$) $list:lcsi$ end object
CeStr loc op lcsi object $opt:op$ $list:lcsi$ end object
CeTyc loc ce ct ($ce$ : $ct$) class type constraint

class_type

Node <:class_type< ... >> Comment
CtAcc loc ct1 ct2 $ct1$ . $ct2$ access
CtApp loc ct1 ct2 $ct1$ $ct2$ application
CtCon loc ct lt $ct$ [ $list:lt$ ] constructor
CtFun loc t ct [ $t$ ] -> $ct$ arrow
CtIde loc s $id:s$ identifier
CtSig loc None lcsi object $list:lcsi$ end object
CtSig loc (Some t) lcsi object ($t$) $list:lcsi$ end object
CtSig loc ot lcsi object $opt:ot$ $list:lcsi$ end object

class_str_item

Node <:class_str_item< ... >> Comment
CrCtr loc t1 t2 type $t1$ = $t2$ type constraint
CrDcl loc lcsi declare $list:lcsi$ end declaration list
CrInh loc ce None inherit $ce$ inheritance
CrInh loc ce (Some s) inherit $ce$ $opt:Some s$ inheritance
CrInh loc ce os inherit $ce$ $opt:os$ inheritance
CrIni loc e initializer $e$ initialization
CrMth loc True True s None e method! private $lid:s$ = $e$ method
CrMth loc True True s (Some t) e method! private $lid:s$ : $t$ = $e$ method
CrMth loc True True s ot e method! private $lid:s$ $opt:ot$ = $e$ method
CrMth loc True False s None e method! $lid:s$ = $e$ method
CrMth loc True False s (Some t) e method! $lid:s$ : $t$ = $e$ method
CrMth loc True False s ot e method! $lid:s$ $opt:ot$ = $e$ method
CrMth loc True b2 s None e method! $priv:b2$ $lid:s$ = $e$ method
CrMth loc True b2 s (Some t) e method! $priv:b2$ $lid:s$ : $t$ = $e$ method
CrMth loc True b2 s ot e method! $priv:b2$ $lid:s$ $opt:ot$ = $e$ method
CrMth loc False True s None e method private $lid:s$ = $e$ method
CrMth loc False True s (Some t) e method private $lid:s$ : $t$ = $e$ method
CrMth loc False True s ot e method private $lid:s$ $opt:ot$ = $e$ method
CrMth loc False False s None e method $lid:s$ = $e$ method
CrMth loc False False s (Some t) e method $lid:s$ : $t$ = $e$ method
CrMth loc False False s ot e method $lid:s$ $opt:ot$ = $e$ method
CrMth loc False b2 s None e method $priv:b2$ $lid:s$ = $e$ method
CrMth loc False b2 s (Some t) e method $priv:b2$ $lid:s$ : $t$ = $e$ method
CrMth loc False b2 s ot e method $priv:b2$ $lid:s$ $opt:ot$ = $e$ method
CrMth loc b1 True s None e method $!:b1$ private $lid:s$ = $e$ method
CrMth loc b1 True s (Some t) e method $!:b1$ private $lid:s$ : $t$ = $e$ method
CrMth loc b1 True s ot e method $!:b1$ private $lid:s$ $opt:ot$ = $e$ method
CrMth loc b1 False s None e method $!:b1$ $lid:s$ = $e$ method
CrMth loc b1 False s (Some t) e method $!:b1$ $lid:s$ : $t$ = $e$ method
CrMth loc b1 False s ot e method $!:b1$ $lid:s$ $opt:ot$ = $e$ method
CrMth loc b1 b2 s None e method $!:b1$ $priv:b2$ $lid:s$ = $e$ method
CrMth loc b1 b2 s (Some t) e method $!:b1$ $priv:b2$ $lid:s$ : $t$ = $e$ method
CrMth loc b1 b2 s ot e method $!:b1$ $priv:b2$ $lid:s$ $opt:ot$ = $e$ method
CrVal loc True True s e value! mutable $lid:s$ = $e$ value
CrVal loc True False s e value! $lid:s$ = $e$ value
CrVal loc True b2 s e value! $flag:b2$ $lid:s$ = $e$ value
CrVal loc False True s e value mutable $lid:s$ = $e$ value
CrVal loc False False s e value $lid:s$ = $e$ value
CrVal loc False b2 s e value $flag:b2$ $lid:s$ = $e$ value
CrVal loc b1 True s e value $!:b1$ mutable $lid:s$ = $e$ value
CrVal loc b1 False s e value $!:b1$ $lid:s$ = $e$ value
CrVal loc b1 b2 s e value $!:b1$ $flag:b2$ $lid:s$ = $e$ value
CrVav loc True s t value virtual mutable $lid:s$ : $t$ virtual value
CrVav loc False s t value virtual $lid:s$ : $t$ virtual value
CrVav loc b s t value virtual $flag:b$ $lid:s$ : $t$ virtual value
CrVir loc True s t method virtual private $lid:s$ : $t$ virtual method
CrVir loc False s t method virtual $lid:s$ : $t$ virtual method
CrVir loc b s t method virtual $flag:b$ $lid:s$ : $t$ virtual method

class_sig_item

Node <:class_sig_item< ... >> Comment
CgCtr loc t1 t2 type $t1$ = $t2$ type constraint
CgDcl loc lcsi declare $list:lcsi$ end declare
CgInh loc ct inherit $ct$ inheritance
CgMth loc True s t method private $lid:s$ : $t$ method
CgMth loc False s t method $lid:s$ : $t$ method
CgMth loc b s t method $flag:b$ $lid:s$ : $t$ method
CgVal loc True s t value mutable $lid:s$ : $t$ value
CgVal loc False s t value $lid:s$ : $t$ value
CgVal loc b s t value $flag:b$ $lid:s$ : $t$ value
CgVir loc True s t method virtual private $lid:s$ : $t$ virtual method
CgVir loc False s t method virtual $lid:s$ : $t$ virtual method
CgVir loc b s t method virtual $flag:b$ $lid:s$ : $t$ virtual method

other

type_decl

What is after 'type' or 'and' in a type declaration.

Node <:type_decl< ... >>
{tdNam=ls;tdPrm=ltv;tdPrv=True;tdDef=t;tdCon=ltt} $tp:ls$ $list:ltv$ = private $t$ $list:ltt$
{tdNam=ls;tdPrm=ltv;tdPrv=False;tdDef=t;tdCon=ltt} $tp:ls$ $list:ltv$ = $t$ $list:ltt$
{tdNam=ls;tdPrm=ltv;tdPrv=b;tdDef=t;tdCon=ltt} $tp:ls$ $list:ltv$ = $priv:b$ $t$ $list:ltt$

with_constr

"With" possibly following a module type.

Node <:with_constr< ... >> Comment
WcMod loc ls me module $list:ls$ = $me$ with module
WcMos loc ls me module $list:ls$ := $me$ with module substitution
WcTyp loc ls ltv True t type $list:ls$ $list:ltv$ = private $t$ with type
WcTyp loc ls ltv False t type $list:ls$ $list:ltv$ = $t$ with type
WcTyp loc ls ltv b t type $list:ls$ $list:ltv$ = $flag:b$ $t$ with type
WcTys loc ls ltv t type $list:ls$ $list:ltv$ := $t$ with type substitution

poly_variant

Polymorphic variants.

Node <:poly_variant< ... >> Comment
PvTag loc s True [] `$s$ constructor
PvTag loc s True lt `$s$ of & $list:lt$ constructor
PvTag loc s False lt `$s$ of $list:lt$ constructor
PvTag loc s b lt `$s$ of $flag:b$ $list:lt$ constructor
PvInh loc t $t$ type
camlp5-rel8.00.02/doc/htmlp/bparsers.html000066400000000000000000000153711410261051500201470ustar00rootroot00000000000000 backtracking parsers

Backtracking parsers

Backtracking parsers are a second alternative of stream parsers and functional parsers.

Backtracking parsers are close to functional parsers: they use the same stream type, "Fstream.t", and their syntax is almost identical, its introducing keyword being "bparser" instead of "fparser".

The difference is that they are implemented with full backtracking and that they return values of the type "option" of the triplet: 1/ value, 2/ remaining stream and 3/ continuation.

Syntax

The syntax of backtracking parsers is added together with the syntax of functional parsers, when the kit "pa_fstream.cmo" is loaded. It is:

          expression ::= bparser
                       | match-with-bparser
             bparser ::= "bparser" pos-opt "[" parser-cases "]"
                       | "bparser" pos-opt parser-case
  match-with-bparser ::= "match" expression "with" bparser
        parser-cases ::= parser-cases parser-case
                       | <nothing>
         parser-case ::= "[:" stream-pattern ":]" pos-opt "->" expression
                       | "[:" ":]" pos-opt "->" expression
      stream-pattern ::= stream-patt-comp
                       | stream-patt-comp ";" stream-pattern
    stream-patt-comp ::= "`" pattern
                       | "`" pattern "when" expression
                       | pattern "=" expression
                       | pattern
                       | "when" expression
             pos-opt ::= pattern
                       | <nothing>

Semantics

Algorithm

The backtracking parsers, like classical parsers and functional parsers, use a recursive descent algorithm. But:

  • If a stream pattern component does not match the current position of the input stream, the control is given to the next case of the stream pattern component before it. If it is the first stream pattern component, the rule (the stream pattern) is left and the next rule is tested.

For example, the following grammar:

   E -> X Y
   X -> a b | a
   Y -> b

works, with the backtracking algorithm, for the input "a b".

Parsing with the non-terminal "E", the non-terminal "X" first accepts the input "a b" with its first rule. Then when "Y" is called, the parsing fails since nothing remains in the input stream.

In the rule "X Y" of the non-terminal "E", the non-terminal "Y" having failed, the control is given the the continuation of the non-terminal "X". This continuation is its second rule containing only "a". Then "Y" is called and accepted.

This case does not work with functional parsers since when the rule "a b" of the non-terminal "X" is accepted, it is definitive. If the input starts with "a b", there is no way to apply its second rule.

Backtracking parsers are strictly more powerful than functional parsers.

Type

A backtracking parser whose stream elements are of type "t1", and whose semantic actions are of some type "t2", is of type:

   Fstream.t t1 -> option (t * Fstream.t t1 * Fstream.kont t1 t2)

If the backtracking parsers fails, its returning value is "None".

If it succeeds, its returning value is "Some (x, strm, k)" where "x" is its result, "strm" the remaining stream, and "k" the continuation.

The continuation is internally used in the backtracking algorithm, but is can also be used in the main call to compute the next solution, using the function "Fstream.bcontinue".

It is also possible to directly get the list of all solutions by calling the function "Fstream.bparse_all".

Syntax errors

Like for functional parsers, in case of syntax error, the error position can be found by using the function "Fstream.count_unfrozen", the token in error being the last unfrozen element of the stream.

A syntax error is not really an error: for the backtracking parsers, like for functional parsers, it is viewed as a "non-working" case and another solution is searched.

In the backtracking algorithm, depending on the grammar and the input, the search of the next solution can be very long. A solution is proposed for that in the extensible grammars system when the parsing algorithm is set to "backtracking".

Example

Here is an example which just shows the backtracking algorithm but without parsing, an empty stream being given as parameter and never referred.

It creates a list of three strings, each of them being choosen between "A", "B" and "C".

The code is:

  #load "pa_fstream.cmo";
  value choice = bparser [ [: :] -> "A" | [: :] -> "B" | [: :] -> "C" ];
  value combine = bparser [: x = choice; y = choice; z = choice :] -> [x; y; z];

The function "combine" returns the first solution:

  # combine (fstream [: :]);
  - : option (list string * Fstream.t '_a * Fstream.kont '_a (list string)) =
  Some (["A"; "A"; "A"], <abstr>, Fstream.K <fun>)

The function "Fstream.bparse_all" returns the list of all solutions, showing the interest of the backtracking:

  # Fstream.bparse_all combine (fstream [: :]);
  - : list (list string) =
  [["A"; "A"; "A"]; ["A"; "A"; "B"]; ["A"; "A"; "C"]; ["A"; "B"; "A"];
   ["A"; "B"; "B"]; ["A"; "B"; "C"]; ["A"; "C"; "A"]; ["A"; "C"; "B"];
   ["A"; "C"; "C"]; ["B"; "A"; "A"]; ["B"; "A"; "B"]; ["B"; "A"; "C"];
   ["B"; "B"; "A"]; ["B"; "B"; "B"]; ["B"; "B"; "C"]; ["B"; "C"; "A"];
   ["B"; "C"; "B"]; ["B"; "C"; "C"]; ["C"; "A"; "A"]; ["C"; "A"; "B"];
   ["C"; "A"; "C"]; ["C"; "B"; "A"]; ["C"; "B"; "B"]; ["C"; "B"; "C"];
   ["C"; "C"; "A"]; ["C"; "C"; "B"]; ["C"; "C"; "C"]]
camlp5-rel8.00.02/doc/htmlp/camlp5.rss000066400000000000000000000243231410261051500173470ustar00rootroot00000000000000 Camlp5 Camlp5 documentation Mon Sep 17 15:10:47 CEST 2007 http://pauillac.inria.fr/~ddr/camlp5/doc/html/ Macros Added ability to use IFDEF and IFNDEF for record labels declarations. Wed Dec 31 11:51:33 CET 2008 ../macros.html Plexer Added flag "Plexer.utf8_lexing" to specify that the lexer built by "Plexer.gmake ()" should take utf8 punctuation characters into account. Mon Dec 24 11:24:34 CET 2007 ../opretty.html quotation example Fixed example in chapter "Quotations" about lambda terms. Did not work because using an old version of the "lexer" syntax extension. Fri Dec 28 23:05:19 CET 2007 ../quot.html pprintf Added chapter about the new statement "pprintf". Fri Dec 28 23:05:19 CET 2007 ../pprintf.html Grammar.Entry.parse_all Added function "Grammar.Entry.parse_all". Thu Dec 27 20:42:30 CET 2007 ../library.html Pretty print Added function "Pretty.horizontally" returning the fact that the current print is horizontal or not. Added function "Prtools.hvlistl" using "hlistl" or "vlistl" according to the fact that the current print is horizontal or not. Mon Dec 24 11:24:34 CET 2007 ../opretty.html Located exceptions Explained in a new section "Located errors" how put locations to exceptions raised in quotations expanders. Sun Dec 16 18:18:08 CET 2007 ../quot.html Backtracking example Added an example of backtracking. Fri Nov 30 12:59:11 CET 2007 ../bparser.html Fstream and Grammar library modules In Fstream module, added section about backtracking parsers. Grammar module, added section about parsing algorithm. They are new features of Camlp5 5.04. Sun Nov 25 08:23:25 CET 2007 ../library.html Backtracking parsers Added chapter about backtracking parsers, a new feature of Camlp5 5.04. Sun Nov 25 03:47:32 CET 2007 ../bparsers.html mkcamlp5 Added paragraph about new commands mkcamlp5 and mkcamlp5.opt. Tue Nov 20 04:30:54 CET 2007 ../commands.html Lexers 2 Updated the chapter about lexers, the lexing buffer being now provided in Camlp5 library, instead of having to be written by the programmer. Thu Oct 11 12:56:15 CEST 2007 ../lexers.html Lexers Changed the chapter about lexers, their syntax being changed. Thu Oct 11 12:56:15 CEST 2007 ../lexers.html Future work Deleted section about the rewritting of the pretty print in Scheme syntax (this is implemented). Added section about GLR grammars. Thu Oct 11 12:56:15 CEST 2007 ../conclusion.html Locations in quotations and antiquotations Added detailed explanations about the problem of locations in quotations and antiquotations. Tue Oct 9 19:10:10 CEST 2007 ../quot.html#a:Locations-in-quotations-and-antiquotations Module Diff and Equilibrated pretty print Added module Diff in Camlp5 library to compare two arrays (using the algorithm of the Unix 'diff' command). Added flag 'E' in pretty print kit in revised syntax (pr_o.cmo) to allow display equilibrate cases (all cases in 'match' statement are cut if one is cut, and same equilibration in 'if' statement). Mon Oct 1 21:47:55 CEST 2007 ../library.html SLIST0... Deleted section about internal extensions SLIST0, SLIST1, SOPT and SFLAG, which are not yet supported. Mon Oct 1 11:38:46 CEST 2007 ../grammars.html Syntax tree - strict mode - nodes without quotations Added a section about types of nodes without quotations: type_var, type_decl and class_infos. Wed Sep 26 14:05:15 CEST 2007 ../ast_strict.html Syntax tree - strict mode - 2 Updated doc of 'patt', 'ctyp', 'str_item' and 'sig_item'. Tue Sep 25 05:14:45 CEST 2007 ../ast_strict.html Version number New version number will be 5.00 instead of 4.09, because the AST quotations in user syntax is a major change. Sat Sep 22 07:14:37 CEST 2007 ../index.html Syntax tree - strict mode - 1 General antiquoting will start with "_" (underscore) instead of "a". Fri Sep 21 21:06:25 CEST 2007 ../ast_strict.html Syntax tree - strict mode Trying a different display for the "expr" quotation, the displaying with a table being to wide. Tue Sep 18 22:35:13 CEST 2007 ../ast_strict.html Syntax tree - 3 Improved the text of the description of the chapters about syntax tree nodes in strict and in transitional modes. Added a chapter (empty for the moment) where the quotation kit "q_ast.cmo" (AST quotations in user syntax) will be specifically described. Tue Sep 18 16:16:23 CEST 2007 ../ml_ast.html Syntax tree - 2 Separated the "syntax tree in strict mode" and "syntax tree in transitional mode" into two chapters. Tue Sep 18 12:15:14 CEST 2007 ../ml_ast.html Syntax tree - 1 Added section about the syntax tree in "strict" mode, actually almost a copy of the section in "transitional" mode. Tue Sep 18 06:34:42 CEST 2007 ../ml_ast.html Future work Changed intro sentence. Deleted section "extensible syntax tree quotations" (implemented). Added section "rewritting pretty printer in Scheme syntax". Tue Sep 18 03:51:21 CEST 2007 ../conclusion.html Syntax tree Changed structure of this chapter. Added introduction to explain the general differences between "transitional" and "strict" modes. Put the rest inside a section "syntax tree in transitional mode". Added a section "syntax tree in strict mode" (to be completed). Mon Sep 17 15:10:47 CEST 2007 ../ml_ast.html Library - module Ploc Explained that this module also contains pervasive type and function. Commented the pervasive type Ploc.vala and added the pervasive function Ploc.call_with. Mon Sep 17 11:41:44 CEST 2007 ../library.html Transitional and Strict - 1 Added more explanations about the two modes, and a short example of what the syntax tree quotation "q_ast.cmo" allows to do. Mon Sep 17 06:29:44 CEST 2007 ../strict.html Transitional and Strict Added chapter about "strict" and "transitional", allowing to choose between backward compatibility and a new feature: the syntax tree quotations in user syntax ("q_ast.cmo"). Mon Sep 17 05:28:48 CEST 2007 ../strict.html camlp5-rel8.00.02/doc/htmlp/commands.html000066400000000000000000000320111410261051500201150ustar00rootroot00000000000000 Commands and Files

Commands and Files

The main command of Camlp5 is "camlp5". It is an OCaml program in bytecode (compiled with ocamlc, not ocamlopt), able to dynamically load OCaml object files (ending with ".cmo" and ".cma").

Most other Camlp5 commands derive from that one: they are the command "camlp5" with some implicitely applied parameters.

Two other commands are provided: "mkcamlp5" and "mkcamlp5.opt". They allow to create camlp5 executables with already loaded kits.

All commands have an option "-help" which display all possible command parameters and options. Notice that some parameters (the parsing and pretting kits) may add new options. For example, the command:

  camlp5 pr_r.cmo -help

prints more lines than just:

  camlp5 -help

The first parameter ("load options") allows to specify parsing and printing kits (".cmo" and ".cma" files) which are loaded inside the "camlp5" core before any action. Other options may follow.

Parsing and Printing Kits

Parsing kits

language parsing kits

pa_r.cmo
Revised syntax (without parsers).
pa_rp.cmo
Add revised syntax parsers.
pa_o.cmo
Normal syntax (without parsers). Option added:
-no_quot
don't parse quotations, allowing to use, e.g. "<:>" as token.
pa_op.cmo
Add normal syntax parsers.
pa_oop.cmo
Add normal syntax parsers without code optimization.
pa_lexer.cmo
Add stream lexers.

extensible grammars

pa_extend.cmo
Add the EXTEND statement. Options added:
-split_ext
split EXTEND by functions to turn around a PowerPC problem.
-quotify
generate code for quotations (internally used to synchronize q_MLast and pa_r)
-meta_action
undocumented (internally used for compiled version)
pa_extfold.cmo
Add the specific symbols FOLD0 and FOLD1 to the EXTEND statement.

extensible functions and printers

pa_extfun.cmo
Add the extensible function ("extfun" statement).
pa_extprint.cmo
Add the EXTEND_PRINTER statement.

functional parsers

pa_fstream.cmo
Add the functional parsers ("fparser" statement) and the backtracking parsers ("bparser" statement).

other languages

pa_lisp.cmo
Lisp syntax.
pa_scheme.cmo
Scheme syntax.
pa_sml.cmo
SML syntax.

other parsing kits

pa_lefteval.cmo
Add guarantee of left evaluation in functions calls.
pa_macro.cmo
Add macros. Options added:
-D <string>
define for IFDEF statement
-U <string>
undefine for IFDEF statement
-defined
print the defined macros and exit
pa_pragma.cmo
Add pragma directive: evaluations at parse time

Printing kits

language printing kits

pr_r.cmo
Display in revised syntax. Added options:
-flag <str>
Change pretty printing behaviour according to "<str>":
A/a enable/disable all flags
C/c enable/disable comments in phrases
D/d enable/disable allowing expanding 'declare'
E/e enable/disable equilibrate cases
L/l enable/disable allowing printing 'let..in' horizontally
S/s enable/disable printing sequences beginners at end of lines
default setting is "aS".
-wflag <str>
Change displaying 'where' statements instead of 'let':
A/a enable/disable all flags
I/i enable/disable 'where' after 'in'
L/l enable/disable 'where' after 'let..='
M/m enable/disable 'where' after 'match' and 'try'
P/p enable/disable 'where' after left parenthesis
R/r enable/disable 'where' after 'record_field..='
S/s enable/disable 'where' in sequences
T/t enable/disable 'where' after 'then' or 'else'
V/v enable/disable 'where' after 'value..='
W/w enable/disable 'where' after '->'
default setting is "Ars".
-l <length>
Maximum line length for pretty printing (default 78)
-sep_src
Read source file for text between phrases (default).
-sep <string>
Use this string between phrases instead of reading source.
pr_ro.cmo
Add display objects, labels and variants in revised syntax.
pr_rp.cmo
Add display parsers with their (revised) syntax.
pr_o.cmo
Display in normal syntax. Added options:
-flag <str>
Change pretty printing behaviour according to <str>:
A/a enable/disable all flags
C/c enable/disable comments in phrases
E/e enable/disable equilibrate cases
L/l enable/disable allowing printing 'let..in' horizontally
M/m enable/disable printing double semicolons
default setting is "Am".
-l <length>
Maximum line length for pretty printing (default 78)
-sep_src
Read source file for text between phrases (default).
-sep <string>
Use this string between phrases instead of reading source.
pr_op.cmo
Add displaying parsers with their (normal) syntax.

extensible parsers

pr_extend.cmo
Add the displaying of EXTEND statements in their initial syntax.Option added:
-no_slist
Don't reconstruct SLIST, SOPT, SFLAG

extensible functions and printers

pr_extfun.cmo
Add displaying extensible functions ("extfun" statement) in their initial syntax.
pr_extprint.cmo
Add displaying extensible printers ("EXTEND_PRINTER" statement) in their initial syntax.

other language

pr_scheme.cmo
Display in Scheme syntax. Option added:
-l <length>
Maximum line length for pretty printing (default 78)
-sep <string>
Use this string between phrases instead of reading source.
pr_schemep.cmo
Add display parsers with their (Scheme) syntax.

other printing kits

pr_depend.cmo
Display dependencies. Option added:
-I dir
Add "dir" to the list of search directories.
pr_dump.cmo
Dump the syntax tree in binary (for the OCaml compiler)
pr_null.cmo
No output.

Quotations expanders

q_MLast.cmo
Syntax tree quotations. Define the quotations named: "expr", "patt", "ctyp", "str_item", "sig_item", "module_type", "module_expr", "class_type", "class_expr", "class_sig_item", "class_str_item", "with_constr" and "poly_variant".
q_phony.cmo
Transform quotations into phony variables to be able to pretty print the quotations in their initial form (not suitable for compilation)

Commands

camlp5r
Shortcut for "camlp5 pa_r.cmo pa_rp.cmo pr_dump.cmo"
camlp5r.opt
Same as previous, but in native code instead of bytecode, therefore faster. But not extensible: it is not possible to add other parsing or printing kits neither in command arguments nor with the "load" directive inside sources. Suitable for compiling sources not using other syntax extensions.
camlp5o
Shortcut for "camlp5 pa_o.cmo pa_op.cmo pr_dump.cmo"
camlp5o.opt
Same as previous, and like "camlp5r.opt", faster and not extensible. Moreover, this has been produced by compilation of Camlp5 grammars, resulting in a still faster executable.
camlp5sch
Shortcut for "camlp5 pa_scheme.cmo pr_dump.cmo"
mkcamlp5
creates camlp5 executables with almost the same options than ocamlmktop. The interfaces to be visible must be explicitly added in the command line as ".cmi" files. For example, how to add the the OCaml module "str": "mkcamlp5 -custom str.cmi str.cma -cclib -lstr -o camlp5str"
mkcamlp5.opt
creates camlp5 executables like mkcamlp5, except that it is in native code, therefore faster, but not extensible; the added kits must be cmx or cmxa files

Environment variable

When running a program using extensible grammars (in particular, the camlp5 commands), the environment variable "CAMLP5PARAM" is consulted. It sets the grammar parsing algoritm parameters.

This variable must be a sequence of parameter specifications. A parameter specification is a letter optionally followed by an = and a value, with any separator. There are four possible parameters:

b
Set the full backtrack algorithm as default.
f
Set the limited backtrack algorithm as default.
t
Trace symbols (terminals and non-terminals) while parsing with backtracking.
y
In backtracking, trace the advance in the input stream (number of unfrozen tokens) and the possible stalling (number of tokens tests).
l=value
Set the maximum stalling value.

OCaml toplevel files

These object files can be loaded in the OCaml toplevel to make Camlp5 parse the input. It is possible to load them either by putting them as parameters of the toplevel, or by using the directive "load". The option "-I +camlp5" (or "-I `camlp5 -where`") must be added to the "ocaml" command (the OCaml toplevel).

camlp5r.cma
Read phrases and display results in revised syntax
camlp5o.cma
Read phrases and display results in normal syntax
camlp5sch.cma
Read phrases in Scheme syntax

Library files

The Camlp5 library is named "gramlib.cma" and its native code version is "gramlib.cmxa". They contain the modules:

This is a pure library : when linking with it, the Camlp5 program is not included.

camlp5-rel8.00.02/doc/htmlp/conclusion.html000066400000000000000000000022761410261051500205020ustar00rootroot00000000000000 Conclusion

Future work

Just some ideas... things to implement or to think about...

extensible lexers

Extensible lexers would be an interesting extension. And possibly lexers using regular expressions (extensible if possible, otherwise as a different module).

utf-8

The Camlp5 lexer for OCaml programs (module Plexer) allows utf-8 characters. Since utf-8 seems to have some success among unicode formats, perhaps a reflection to add greek characters and/or real utf-8 arrows in the syntax (in particular in types) would be interesting.

camlp5-rel8.00.02/doc/htmlp/directives.html000066400000000000000000000102451410261051500204620ustar00rootroot00000000000000 Directives

Directives

Directives in normal or revised syntax are statements at top level, or, more generally, as signature items or structure items, which stops the preprocessor for evaluate things - which can change the behaviour of the preprocessor, for example to add syntax, load syntax extensions and so on. After the directive is evaluated, the parsing resumes.

Directives begin with '#', followed by an identifier, and, optionnally by an expression. They are usable in source files the and generally in the ocaml toplevel too.

Four predefined directives exist: #load, #directory, #option and #use. It is also possible to add other directives. An example of that is the parsing kit pa_pragma.cmo which adds a new directive #pragma.

Predefined directives

The predefined directives are:

#load "name"

Loads an object file (ocaml cmo or cma file) in the core, evaluating it. This is typically to be used in the ocaml toplevel to add an syntax extension kit.

For example, in the toplevel, loading the quotation expander of ocaml syntax trees:

  # #load "q_MLast.cmo";

  # value loc = Ploc.dummy;
  value loc : Ploc.t = <abstr>

  # <:expr< fun x -> x >>;
  - : MLast.expr =
  MLast.ExFun <abstr>
    (Ploc.VaVal
       [(MLast.PaLid <abstr> (Ploc.VaVal "x"), Ploc.VaVal None,
         MLast.ExLid <abstr> (Ploc.VaVal "x"))])

In a source file, the '#load' directive is equivalent to put the object file as camlp5 parameter among the 'load options':

   $ cat myfile.ml

   #load "pa_extend.cmo";
   value g = Grammar.gcreate (Plexer.gmake ());
   value e = Grammar.Entry.create g "e";

   EXTEND e: [[ i = INT -> i ]]; END;

   $ ocamlc -pp camlp5r -I +camlp5 -c myfile.ml

which is equivalent to, without using '#load':

   $ cat myfile2.ml

   value g = Grammar.gcreate (Plexer.gmake ());
   value e = Grammar.Entry.create g "e";

   EXTEND e: [[ i = INT -> i ]]; END;

and compiling it like this:

   $ ocamlc -pp 'camlp5r pa_extend.cmo' -I +camlp5 -c myfile2.ml

#directory "name"

Adds a new directory in the camlp5 path searching for loaded files (using the directive #load above). This is equivalent to the option '-I' of the camlp5 command. See the camlp5 man page.

#use "name"

Loads a source file name. Useful in the ocaml toplevel to test a source file.

#option "option"

Adds an option as if it were added in camlp5 command line (to be used in a source file, not in the ocaml toplevel). Implemented only on options without an extra parameter.

For example, the syntax kit pa_extend.cmo adds an option named '-split_ext'. This can be viewed through the command:

  camlp5r pa_extend.cmo -help

Thanks to the directive '#option', the following command in the shell:

  $ camlp5r pa_extend.cmo -split_ext file.ml

can be used only as:

  $ camlp5r file.ml

providing the file starts with:

  #load "pa_extend.cmo";
  #option "-split_ext";

User directives

It is possible to add any extra directive. The syntax kit pragma.cmo, for example, adds a directive named '#pragma'.

A user syntax kit can add its directives using the function "add_directive" of the module Pcaml.

camlp5-rel8.00.02/doc/htmlp/extfun.html000066400000000000000000000072401410261051500176330ustar00rootroot00000000000000 Extensible functions

Extensible functions

Extensible functions allows the definition of pattern matching functions which are extensible by adding new cases that are inserted automatically at the proper place by comparing the patterns. The pattern cases are ordered according to syntax trees representing them, "when" statements being inserted before the cases without "when".

Notice that extensible functions are functional: when extending a function, a new function is returned.

The extensible functions are used in the pretty printing system of Camlp5.

Syntax

The syntax of the extensible functions, when loading "pa_extfun.cmo", is the following:

           expression ::= extensible-function
  extensible-function ::= "extfun" expression "with" "[" match-cases "]"
          match-cases ::= match-case "|" match-cases
           match-case ::= pattern "->" expression
                        | pattern "when" expression "->" expression

It is an extension of the same syntax as the "match" and "try" constructions.

Semantics

The statement "extend" defined by the syntax takes an extensible function and return another extensible function with the new match cases inserted at the proper place within the initial extensible function.

Extensible functions are of type "Extfun.t a b", which is an abstract type, where "a" and "b" are respectively the type of the patterns and the type of the expressions. It corresponds to a function of type "a -> b".

The function "Extfun.apply" takes an extensible function as parameter and returns a function which can be applied like a normal function.

The value "Extfun.empty" is an empty extensible function, of type "Extfun.t 'a 'b". When applied with "Extfun.apply" and a parameter, it raises the exception "Extfun.Failure" whatever the parameter.

For debugging, it is possible to use the function "Extfun.print" which displays the match cases of the extensible functions. (Only the patterns are displayed in clear text, the associated expressions are not.)

The match cases are inserted according to the following rules:

  • The match cases are inserted in the order they are defined in the syntax "extend"
  • A match case pattern with "when" is inserted before a match case pattern without "when".
  • Two match cases patterns both with "when" or both without "when" are inserted according to the alphabetic order of some internal syntax tree of the patterns where bound variables names are not taken into account.
  • If two match cases patterns without "when" have the same patterns internal syntax tree, the initial one is silently removed.
  • If two match cases patterns with "when" have the same patterns internal syntax tree, the new one is inserted before the old one.
camlp5-rel8.00.02/doc/htmlp/fparsers.html000066400000000000000000000140111410261051500201410ustar00rootroot00000000000000 functional parsers

Functional parsers

Purely functional parsers are an alternative of stream parsers where the used stream type is a lazy non-destructive type. These streams are lazy values, as in classical stream parsers, but the values are not removed as long as the parsing advances.

To make them work, the parsers of purely functional streams return, not the simple values, but a value of type option : "None" meaning "no match" (the equivalent of the exception "Parse.Failure" of normal streams) and "Some (r, s)" meaning "the result is r and the remaining stream is s".

Syntax

The syntax of purely functional parsers, when loading "pa_fstream.cmo", is the following:

          expression ::= fparser
                       | match-with-fparser
             fparser ::= "fparser" pos-opt "[" parser-cases "]"
                       | "fparser" pos-opt parser-case
  match-with-fparser ::= "match" expression "with" fparser
        parser-cases ::= parser-cases parser-case
                       | <nothing>
         parser-case ::= "[:" stream-pattern ":]" pos-opt "->" expression
                       | "[:" ":]" pos-opt "->" expression
      stream-pattern ::= stream-patt-comp
                       | stream-patt-comp ";" stream-pattern
    stream-patt-comp ::= "`" pattern
                       | "`" pattern "when" expression
                       | pattern "=" expression
                       | pattern
                       | "when" expression
             pos-opt ::= pattern
                       | <nothing>

Notice that, unlike classical parsers, there is no difference, in a stream pattern, between the first stream pattern component and the other ones. In particular, there is no "question mark" syntax and expression optionnally ending those components. Moreover, the "lookahead" case is not necessary, we see further why. The syntaxes "pattern when" and "let..in" inside stream patterns we see in classical parsers are not implemented.

Streams

The functional parsers are functions taking as parameters functional streams, which are values of type "Fstream.t a" for some type "a". It is possible to build functional streams using the functions defined in the module "Fstream":

Fstream.from

"Fstream.from f" returns a stream built from the function "f". To create a new stream element, the function "f" is called with the current stream count, starting with zero. The user function "f" must return either "Some <value>" for a value or "None" to specify the end of the stream.

Fstream.of_list

Return a stream built from the list in the same order.

Fstream.of_string

Return a stream of the characters of the string parameter.

Fstream.of_channel

Return a stream of the characters read from the input channel parameter.

Semantics of parsers

Fparser

The purely functional parsers act like classical parsers, with a recursive descent algorithm, except that:

  • If the first stream pattern component matches the beginning of the stream, there is no error if the following stream patterns components do not match: the control simply passes to the next parser case with the initial stream.
  • If the semantic actions are of type "t", the result of the parser is of type "option (t * Fstream.t)", not just "t" like in classical parsers. If a stream pattern matches, the semantic action is evaluated, giving some result "e" and the result of the parser is "Some (e, strm)" where "strm" is the remaining stream.
  • If no parser case matches, the result of the parser is "None".

Error position

A difficulty, with purely functional parsers, is how to find the position of the syntax error, when the input is wrong. Since the system tries all parsers cases before returning "None", and that the initial stream is not affected, it is not possible to directly find where the error happened. This is a problem for parsing using backtracking (here, it is limited backtracking, but the problem is the same).

The solution is to use the function "Fstream.count_unfrozen" applied to the initial stream. Like its name says, it returns the number of unfrozen elements of the stream, which is exactly the longest match found. If the input is a stream of characters, the return of this function is exactly the position in number of characters from the beginning of the stream.

However, it is not possible to know directly which rule failed and therefore it is not possible, as in classical parsers, to specify and get clear error messages. Future versions of purely functional parsers may propose solutions to resolve this problem.

Notice that, if using the "count_unfrozen" method, it is not possible to reuse that same stream to call another parser, and hope to get the right position of the error, if another error happens, since it may test less terminals than the first parser. Use a fresh stream in this case, if possible.

camlp5-rel8.00.02/doc/htmlp/grammars.html000066400000000000000000001222651410261051500201400ustar00rootroot00000000000000 extensible grammars

Extensible grammars

This chapter describes the syntax and semantics of the extensible grammars of Camlp5.

The extensible grammars are the most advanced parsing tool of Camlp5. They apply to streams of characters using a lexer which has to be previously defined by the programmer. In Camlp5, the syntax of the OCaml language is defined with extensible grammars, which makes Camlp5 a bootstrapped system (it compiles its own features by itself).

Getting started

The extensible grammars are a system to build grammar entries which can be extended dynamically. A grammar entry is an abstract value internally containing a stream parser. The type of a grammar entry is "Grammar.Entry.e t" where "t" is the type of the values returned by the grammar entry.

To start with extensible grammars, it is necessary to build a grammar, a value of type "Grammar.g", using the function "Grammar.gcreate":

  value g = Grammar.gcreate lexer;

where "lexer" is a lexer previously defined. See the section explaining the interface with lexers. In a first time, it is possible to use a lexer of the module "Plexer" provided by Camlp5:

  value g = Grammar.gcreate (Plexer.gmake ());

Each grammar entry is associated with a grammar. Only grammar entries of the same grammar can call each other. To create a grammar entry, one has to use the function "Grammar.Entry.create" with takes the grammar as first parameter and a name as second parameter. This name is used in case of syntax errors. For example:

  value exp = Grammar.Entry.create g "expression";

To apply a grammar entry, the function "Grammar.Entry.parse" can be used. Its first parameter is the grammar entry, the second one a stream of characters:

  Grammar.Entry.parse exp (Stream.of_string "hello");

But if you experiment this, since the entry was just created without any rules, you receive an error message:

  Stream.Error "entry [expression] is empty"

To add grammar rules to the grammar entry, it is necessary to extend it, using a specific syntactic statement: "EXTEND".

Syntax of the EXTEND statement

The "EXTEND" statement is added in the expressions of the OCaml language when the syntax extension kit "pa_extend.cmo" is loaded. Its syntax is:

    expression ::= extend
        extend ::= "EXTEND" extend-body "END"
   extend-body ::= global-opt entries
    global-opt ::= "GLOBAL" ":" entry-names ";"
                 | <nothing>
   entry-names ::= entry-name entry-names
                 | entry-name
         entry ::= entry-name ":" position-opt "[" levels "]"
  position-opt ::= "FIRST"
                 | "LAST"
                 | "BEFORE" label
                 | "AFTER" label
                 | "LIKE" string
                 | "LEVEL" label
                 | <nothing>
        levels ::= level "|" levels
                 | level
         level ::= label-opt assoc-opt "[" rules "]"
     label-opt ::= label
                 | <nothing>
     assoc-opt ::= "LEFTA"
                 | "RIGHTA"
                 | "NONA"
                 | <nothing>
         rules ::= rule "|" rules
                 | rule
          rule ::= psymbols-opt "->" expression
                 | psymbols-opt
  psymbols-opt ::= psymbols
                 | <nothing>
      psymbols ::= psymbol ";" psymbols
                 | psymbol
       psymbol ::= symbol
                 | pattern "=" symbol
        symbol ::= keyword
                 | token
                 | token string
                 | entry-name
                 | entry-name "LEVEL" label
                 | "SELF"
                 | "NEXT"
                 | "LIST0" symbol
                 | "LIST0" symbol "SEP" symbol opt-opt-sep
                 | "LIST1" symbol
                 | "LIST1" symbol "SEP" symbol opt-opt-sep
                 | "OPT" symbol
                 | "FLAG" symbol
                 | "V" symbol opt-strings
                 | "[" rules "]"
                 | "(" symbol ")"
   opt-opt-sep ::= "OPT_SEP"
                 | <nothing>
   opt-strings ::= string opt-strings
                 | <nothing>
       keyword ::= string
         token ::= uident
         label ::= string
    entry-name ::= qualid
        qualid ::= qualid "." qualid
                 | uident
                 | lident
        uident ::= 'A'-'Z' ident
        lident ::= ('a'-'z' | '_' | misc-letter) ident
         ident ::= ident-char*
    ident-char ::= ('a'-'a' | 'A'-'Z' | '0'-'9' | '_' | ''' | misc-letter)
   misc-letter ::= '\128'-'\255'

Other statements, "GEXTEND", "DELETE_RULE", "GDELETE_RULE" are also defined by the same syntax extension kit. See further.

In the description above, only "EXTEND" and "END" are new keywords (reserved words which cannot be used in variables, constructors or module names). The other strings (e.g. "GLOBAL", "LEVEL", "LIST0", "LEFTA", etc.) are not reserved.

Semantics of the EXTEND statement

The EXTEND statement starts with the "EXTEND" keyword and ends with the "END" keyword.

GLOBAL indicator

After the first keyword, it is possible to see the identifier "GLOBAL" followed by a colon, a list of entries names and a semicolon. It says that these entries correspond to visible (previously defined) entry variables, in the context of the EXTEND statement, the other ones being locally and silently defined inside.

  • If an entry, which is extended in the EXTEND statement, is in the GLOBAL list, but is not defined in the context of the EXTEND statement, the OCaml compiler will fail with the error "unbound value".
  • If there is no GLOBAL indicator, and an entry, which is extended in the EXTEND statement, is not defined in the contex of the EXTEND statement, the OCaml compiler will also fail with the error "unbound value".

Example:

  value exp = Grammar.Entry.create g "exp";
  EXTEND
    GLOBAL: exp;
    exp: [ [ x = foo; y = bar ] ];
    foo: [ [ "foo" ] ];
    bar: [ [ "bar" ] ];
  END;

The entry "exp" is an existing variable (defined by value exp = ...). On the other hand, the entries "foo" and "bar" have not been defined. Because of the GLOBAL indicator, the system define them locally.

Without the GLOBAL indicator, the three entries would have been considered as global variables, therefore the OCaml compiler would say "unbound variable" under the first undefined entry, "foo".

Entries list

Then the list of entries extensions follow. An entry extension starts with the entry name followed by a colon. An entry may have several levels corresponding to several stream parsers which call the ones the others (see further).

Optional position

After the colon, it is possible to specify a where to insert the defined levels:

  • The identifier "FIRST" (resp. "LAST") indicates that the level must be inserted before (resp. after) all possibly existing levels of the entry. They become their first (resp. last) levels.
  • The identifier "BEFORE" (resp. "AFTER") followed by a level label (a string) indicates that the levels must be inserted before (resp. after) that level, if it exists. If it does not exist, the extend statement fails at run time.
  • The identifier "LIKE" followed by a string indicates that the first level defined in the extend statement must be inserted in the first already existing level with a rule containing this string as keyword or token name. For example, "LIKE "match"" is the first level having "match" as keyword. If there is no level with this string, the extend statement fails at run time.
  • The identifier "LEVEL" followed by a level label indicates that the first level defined in the extend statement must be inserted at the given level, extending and modifying it. The other levels defined in the statement are inserted after this level, and before the possible levels following this level. If there is no level with this label, the extend statement fails at run time.
  • By default, if the entry has no level, the levels defined in the statement are inserted in the entry. Otherwise the first defined level is inserted at the first level of the entry, extending or modifying it. The other levels are inserted afterwards (before the possible second level which may previously exist in the entry).

Levels

After the optional "position", the level list follow. The levels are separated by vertical bars, the whole list being between brackets.

A level starts with an optional label, which corresponds to its name. This label is useful to specify this level in case of future extensions, using the position (see previous section) or for possible direct calls to this specific level.

The level continues with an optional associativity indicator, which can be:

  • LEFTA for left associativity (default),
  • RIGHTA for right associativity,
  • NONA for no associativity.

Rules

At last, the grammar rule list appear. The rules are separated by vertical bars, the whole list being brackets.

A rule looks like a match case in the "match" statement or a parser case in the "parser" statement: a list of psymbols (see next paragraph) separated by semicolons, followed by a right arrow and an expression, the semantic action. Actually, the right arrow and expression are optional: in this case, it is equivalent to an expression which would be the unit "()" constructor.

A psymbol is either a pattern, followed with the equal sign and a symbol, or by a symbol alone. It corresponds to a test of this symbol, whose value is bound to the pattern if any.

Symbols

A symbol is an item in a grammar rule. It is either:

  • a keyword (a string): the input must match this keyword,
  • a token name (an identifier starting with an uppercase character), optionally followed by a string: the input must match this token (any value if no string, or that string if a string follows the token name), the list of the available tokens depending on the associated lexer (the list of tokens available with "Plexer.gmake ()" is: LIDENT, UIDENT, TILDEIDENT, TILDEIDENTCOLON, QUESTIONIDENT, INT, INT_l, INT_L, INT_n, FLOAT, CHAR, STRING, QUOTATION, ANTIQUOT and EOI; other lexers may propose other lists of tokens),
  • an entry name, which correspond to a call to this entry,
  • an entry name followed by the identifier "LEVEL" and a level label, which correspond to the call to this entry at that level,
  • the identifier "SELF" which is a recursive call to the present entry, according to the associativity (i.e. it may be a call at the current level, to the next level, or to the top level of the entry): "SELF" is equivalent to the name of the entry itself,
  • the identifier "NEXT", which is a call to the next level of the current entry,
  • a left brace, followed by a list of rules separated by vertical bars, and a right brace: equivalent to a call to an entry, with these rules, inlined,
  • a meta symbol (see further),
  • a symbol between parentheses.

The syntactic analysis follow the list of symbols. If it fails, depending on the first items of the rule (see the section about the kind of grammars recognized):

  • the parsing may fail by raising the exception "Stream.Error"
  • the parsing may continue with the next rule.

Meta symbols

Extra symbols exist, allowing to manipulate lists or optional symbols. They are:

  • LIST0 followed by a symbol: this is a list of this symbol, possibly empty,
  • LIST0 followed by a symbol, SEP and another symbol, and optional OPT_SEP: this is a list, possibly empty, of the first symbol separated by the second one, possibly ended with the separator if OPT_SEP is present,
  • LIST1 followed by a symbol: this is a list of this symbol, with at least one element,
  • LIST1 followed by a symbol, SEP and another symbol, and optional OPT_SEP: this is a list, with at least one element, of the first symbol separated by the second one, possibly ended with the separator if OPT_SEP is present,
  • OPT followed by a symbol: equivalent to "this symbol or nothing" returning a value of type "option".
  • FLAG followed by a symbol: equivalent to "this symbol or nothing", returning a boolean.

The V meta symbol

The V meta symbol is destinated to allow antiquotations while using the syntax tree quotation kit q_ast.cmo. It works only in strict mode. In transitional mode, it is just equivalent to its symbol parameter.

Antiquotation kind

The antiquotation kind is the optional identifier between the starting "$" (dollar) and the ":" (colon) in a quotation of syntax tree (see the chapter syntax tree).

The optional list of strings following the "V" meta symbol and its symbol parameter gives the allowed antiquotations kinds.

By default, this string list, i.e. the available antiquotation kinds, is:

  • ["flag"] for FLAG
  • ["list"] for LIST0 and LIST1
  • ["opt"] for OPT

For example, the symbol:

  V (FLAG "rec")

is like "FLAG" while normally parsing, allowing to parse the keyword "rec". While using it in quotations, also allows the parse the keyword "rec" but, moreover, the antiquotation "$flag:..$" where ".." is an expression or a pattern depending on the position of the quotation.

There are also default antiquotations kinds for the tokens used in the OCaml language predefined parsers "pa_r.cmo" (revised syntax) and "pa_o.cmo" (normal syntax), actually all parsers using the provided lexer "Plexer" (see the chapter Library). They are:

  • ["chr"] for CHAR
  • ["flo"] for FLOAT
  • ["int"] for INT
  • ["int32"] for INT_l
  • ["int64"] for INT_L
  • ["nativeint"] for INT_n
  • ["lid"] for LIDENT
  • ["str"] for STRING
  • ["uid"] for UIDENT

It is also possible to use the "V" meta symbol over non-terminals (grammars entries), but there is no default antiquotation kind. For example, while parsing a quotation, the symbol:

  V foo "bar" "oops"

corresponds to either a call to the grammar entry "foo", or to the antiquotations "$bar:...$" or "$oops:...$".

Type

The type of the value returned by a V meta symbol is:

  • in transitional mode, the type of its symbol parameter,
  • in strict mode, "Ploc.vala t", where "t" is its symbol parameter.

In strict mode, if the symbol parameter is found, whose value is, say, "x", the result is "Ploc.VaVal x". If an antiquotation is found the result is "Ploc.VaAnt s" where "s" is some string containing the antiquotation text and some other internal information.

Rules insertion

Remember that "EXTEND" is a statement, not a declaration: the rules are added in the entries at run time. Each rule is internally inserted in a tree, allowing the left factorization of the rule. For example, with this list of rules (borrowed from the Camlp5 sources):

  "method"; "private"; "virtual"; l = label; ":"; t = poly_type
  "method"; "virtual"; "private"; l = label; ":"; t = poly_type
  "method"; "virtual"; l = label; ":"; t = poly_type
  "method"; "private"; l = label; ":"; t = poly_type; "="; e = expr
  "method"; "private"; l = label; sb = fun_binding
  "method"; l = label; ":"; t = poly_type; "="; e = expr
  "method"; l = label; sb = fun_binding

the rules are inserted in a tree and the result looks like:

  "method"
     |-- "private"
     |       |-- "virtual"
     |       |       |-- label
     |       |             |-- ":"
     |       |                  |-- poly_type
     |       |-- label
     |             |-- ":"
     |             |    |-- poly_type
     |             |            |-- ":="
     |             |                 |-- expr
     |             |-- fun_binding
     |-- "virtual"
     |       |-- "private"
     |       |       |-- label
     |       |             |-- ":"
     |       |                  |-- poly_type
     |       |-- label
     |             |-- ":"
     |                  |-- poly_type
     |-- label
           |-- ":"
           |    |-- poly_type
           |            |-- "="
           |                 |-- expr
           |-- fun_binding

This tree is built as long as rules are inserted. When used, by applying the function "Grammar.Entry.parse" to the current entry, the input is matched with that tree, starting from the tree root, descending on it as long as the parsing advances.

There is a different tree by entry level.

Semantic action

The semantic action, i.e. the expression following the right arrow in rules, contains in its environment:

  • the variables bound by the patterns of the symbols found in the rules,
  • the specific variable "loc" which contain the location of the whole rule in the source.

The location is an abstract type defined in the module "Ploc" of Camlp5.

It is possible to change the name of this variable by using the option "-loc" of Camlp5. For example, compiling a file like this:

  camlp5r -loc foobar file.ml

the variable name, for the location will be "foobar" instead of "loc".

The DELETE_RULE statement

The "DELETE_RULE" statement is also added in the expressions of the OCaml language when the syntax extension kit "pa_extend.cmo" is loaded. Its syntax is:

        expression ::= delete-rule
       delete-rule ::= "DELETE_RULE" delete-rule-body "END"
  delete-rule-body ::= entry-name ":" symbols
           symbols ::= symbol symbols
                     | symbol

See the syntax of the EXTEND statement for the meaning of the syntax entries not defined above.

The entry is scanned for a rule matching the giving symbol list. When found, the rule is removed. If no rule is found, the exception "Not_found" is raised.

Extensions FOLD0 and FOLD1

When loading "pa_extfold.cmo" after "pa_extend.cmo", the entry "symbol" of the EXTEND statement is extended with what is named the fold iterators, like this:

       symbol ::= "FOLD0" simple_expr simple_expr symbol
                | "FOLD1" simple_expr simple_expr symbol
                | "FOLD0" simple_expr simple_expr symbol "SEP" symbol
                | "FOLD1" simple_expr simple_expr symbol "SEP" symbol
  simple_expr ::= expr (level "simple")

Like their equivalent with the lists iterators: "LIST0", "LIST1", "LIST0SEP", "LIST1SEP", they read a sequence of symbols, possibly with the separators, but instead of building the list of these symbols, apply a fold function to each symbol, starting at the second "expr" (which must be a expression node) and continuing with the first "expr" (which must be a function taking two expressions and returing a new expression).

The list iterators can be seen almost as a specific case of these fold iterators where the initial "expr" would be:

  <:expr< [] >>

and the fold function would be:

  fun e1 e2 -> <:expr< [$e1$ :: $e2$ ] >>

except that, implemented like that, they would return the list in reverse order.

Actually, a program using them can be written with the lists iterators with the semantic action applying the function "List.fold_left" to the returned list, except that with the fold iterators, this operation is done as long as the symbols are read on the input, no intermediate list being built.

Example, file "sum.ml":

  #load "pa_extend.cmo";
  #load "pa_extfold.cmo";
  #load "q_MLast.cmo";
  let loc = Ploc.dummy in
  EXTEND
    Pcaml.expr:
      [ [ "sum";
          e =
            FOLD0 (fun e1 e2 -> <:expr< $e2$ + $e1$ >>) <:expr< 0 >>
              Pcaml.expr SEP ";";
          "end" -> e ] ]
    ;
  END;

which can be compiled like this:

  ocamlc -pp camlp5r -I +camlp5 -c sum.ml

and tested:

  ocaml -I +camlp5 camlp5r.cma sum.cmo
          Objective Caml version ...

          Camlp5 Parsing version ...

  # sum 3;4;5 end;
- : int = 12

Grammar machinery

We explain here the detail of the mechanism of the parsing of an entry.

Start and Continue

At each entry level, the rules are separated into two trees:

  • The tree of the rules not starting with the current entry name nor by "SELF".
  • The tree of the rules starting with the current entry name or by the identifier "SELF", this symbol not being included in the tree.

They determine two functions:

  • The function named "start", analyzing the first tree.
  • The function named "continue", taking, as parameter, a value previously parsed, and analyzing the second tree.

A call to an entry, using "Grammar.Entry.parse" correspond to a call to the "start" function of the first level of the entry.

The "start" function tries its associated tree. If it works, it calls the "continue" function of the same level, giving the result of "start" as parameter. If this "continue" function fails, this parameter is simply returned. If the "start" function fails, the "start" function of the next level is tested. If there is no more levels, the parsing fails.

The "continue" function first tries the "continue" function of the next level. If it fails, or if it is the last level, it tries its associated tree, then calls itself again, giving the result as parameter. If its associated tree fails, it returns its extra parameter.

Associativity

While testing the tree, there is a special case for rules ending with SELF or with the current entry name. For this last symbol, there is a call to the "start" function: of the current level if the level is right associative, or of the next level otherwise.

There is no behaviour difference between left and non associative, because, in case of syntax error, the system attempts to recover the error by applying the "continue" function of the previous symbol (if this symbol is a call to an entry).

When a SELF or the current entry name is encountered in the middle of the rule (i.e. if it is neither the first nor the last symbol), there is a call to the "start" function of the first level of the current entry.

Example. Let us consider the following grammar:

  EXTEND
    expr:
      [ "minus" LEFTA
        [ x = SELF; "-"; y = SELF -> x -. y ]
      | "power" RIGHTA
        [ x = SELF; "**"; y = SELF -> x ** y ]
      | "simple"
        [ "("; x = SELF; ")" -> x
        | x = INT -> float_of_int x ] ]
    ;
  END

The left "SELF"s of the two levels "minus" and "power" correspond to a call to the next level. In the level "minus", the right "SELF" also, and the left associativity is treated by the fact that the "continue" function is called (starting with the keyword "-" since the left "SELF" is not part of the tree). On the other hand, for the level "power", the right "SELF" corresponds to a call to the current level, i.e. the level "power" again. At end, the "SELF" between parentheses of the level "simple" correspond to a call to the first level, namely "minus" in this grammar.

Parsing algorithm

By default, the kind of grammar is predictive parsing grammar, i.e. recursive descent parsing without backtrack. But with some nuances, due to the improvements (error recovery and token starting rules) indicated in the next sections.

However, it is possible to change the parsing algorithm, by calling the function "Grammar.set_algorithm". The possible values are:

Grammar.Predictive
internally using normal parsers, with a predictive (recursive descent without backtracking) algorithm.
Grammar.Functional
internally using functional parsers, with a limited backtracking algorithm,
Grammar.Backtracking
internally using backtracking parsers, with a full backtracking algorithm,
Grammar.DefaultAlgorithm
the parsing algorithm is determined by the environment variable "CAMLP5PARAM". If this environment variable exists and contains "f", the parsing algorithm is "functional"; if it it "b", the parsing algorithm is "backtracking". Otherwise it is "predictive".

An interesting function, when using then backtracking algorithm, is "Grammar.Entry.parse_all" which returns all solutions of a given input.

See details in the chapter Library, section "Grammar module".

Errors and recovery

In extensible grammars, the exceptions are encapsulated with the exception "Ploc.Exc" giving the location of the error together with the exception itself.

If the parsing algorithm is "Grammar.Predictive", the system internally uses stream parsers. Two exceptions may happen: "Stream.Failure" or "Stream.Error". "Stream.Failure" indicates that the parsing just could not start. "Stream.Error" indicates that the parsing started but failed further.

With this algorithm, when the first symbol of a rule has been accepted, all the symbols of the same rule must be accepted, otherwise the exception "Stream.Error" is raised.

If the parsing algorithm is "Grammar.Functional" (resp. "Grammar.Backtracking"), the system internally uses functional parsers (resp backtracking parsers. If no solution is found, the exception "Stream.Error" is raised and the location of the error is the location of the last unfrozen token, i.e. where the stream advanced the farthest.

In extensible grammars, unlike stream parsers, before the "Stream.Error" exception, the system attempts to recover the error by the following trick: if the previous symbol of the rule was a call to another entry, the system calls the "continue" function of that entry, which may resolve the problem.

Tokens starting rules

Another improvement (other than error recovery) is that when a rule starts with several tokens and/or keywords, all these tokens and keywords are tested in one time, and the possible "Stream.Error" may happen, only from the symbol following them on, if any.

The Grammar module

See its section in the chapter "Library".

Interface with the lexer

To create a grammar, the function "Grammar.gcreate" must be called, with a lexer as parameter.

A simple solution, as possible lexer, is the predefined lexer built by "Plexer.gmake ()", lexer used for the OCaml grammar of Camlp5. In this case, you can just put it as parameter of "Grammar.gcreate" and it is not necessary to read this section.

The section first introduces the notion of "token patterns" which are the way the tokens and keywords symbols in the EXTEND statement are represented. Then follow the description of the type of the parameter of "Grammar.gcreate".

Token patterns

A token pattern is a value of the type defined like this:

  type pattern = (string * string);

This type represents values of the token and keywords symbols in the grammar rules.

For a token symbol in the grammar rules, the first string is the token constructor name (starting with an uppercase character), the second string indicates whether the match is "any" (the empty string) or some specific value of the token (an non-empty string).

For a keyword symbol, the first string is empty and the second string is the keyword itself.

For example, given this grammar rule:

  "for"; i = LIDENT; "="; e1 = SELF; "to"; e2 = SELF

the different symbols and keywords are represented by the following couples of strings:

  • the keyword "for" is represented by ("", "for"),
  • the keyword "=" by ("", "="),
  • the keyword "to" by ("", "to")),
  • and the token symbol LIDENT by ("LIDENT", "").

The symbol UIDENT "Foo" in a rule would be represented by the token pattern:

  ("UIDENT", "Foo")

Notice that the symbol "SELF" is a specific symbol of the EXTEND syntax: it does not correspond to a token pattern and is represented differently. A token constructor name must not belong to the specific symbols: SELF, NEXT, LIST0, LIST1, OPT and FLAG.

The lexer record

The type of the parameter of the function "Grammar.gcreate" is "lexer", defined in the module "Plexing". It is a record type with the following fields:

tok_func

It is the lexer itself. Its type is:

  Stream.t char -> (Stream.t (string * string) * location_function);

The lexer takes a character stream as parameter and return a couple of containing: a token stream (the tokens being represented by a couple of strings), and a location function.

The location function is a function taking, as parameter, a integer corresponding to a token number in the stream (starting from zero), and returning the location of this token in the source. This is important to get good locations in the semantic actions of the grammar rules.

Notice that, despite the lexer taking a character stream as parameter, it is not mandatory to use the stream parsers technology to write the lexer. What is important is that it does the job.

tok_using

Is a function of type:

  pattern -> unit

The parameter of this function is the representation of a token symbol or a keyword symbol in grammar rules. See the section about token patterns.

This function is called for each token symbol and each keyword encountered in the grammar rules of the EXTEND statement. Its goal is to allow the lexer to check that the tokens and keywords do respect the lexer rules. It checks that the tokens exist and are not mispelled. It can be also used to enter the keywords in the lexer keyword tables.

Setting it as the function that does nothing is possible, but the check of correctness of tokens is not done.

In case or error, the function must raise the exception "Plexing.Error" with an error message as parameter.

tok_removing

Is a function of type:

  pattern -> unit

It is possibly called by the DELETE_RULE statement for tokens and keywords no longer used in the grammar. The grammar system maintains a number of usages of all tokens and keywords and calls this function only when this number reaches zero. This can be interesting for keywords: the lexer can remove them from its tables.

tok_match

Is a function of type:

  pattern -> ((string * string) -> unit)

The function tells how a token of the input stream is matched against a token pattern. Both are represented by a couple of strings.

This function takes a token pattern as parameter and return a function matching a token, returning the matched string or raising the exception "Stream.Failure" if the token does not match.

Notice that, for efficiency, it is necessary to write this function as a match of token patterns returning, for each case, the function which matches the token, not a function matching the token pattern and the token together and returning a string for each case.

An acceptable function is provided in the module "Plexing" and is named "default_match". Its code looks like this:

  value default_match =
    fun
    [ (p_con, "") ->
        fun (con, prm) -> if con = p_con then prm else raise Stream.Failure
    | (p_con, p_prm) ->
        fun (con, prm) ->
          if con = p_con && prm = p_prm then prm else raise Stream.Failure ]
  ;

tok_text

Is a function of type:

  pattern -> string

Designed for error messages, it takes a token pattern as parameter and returns the string giving its name.

It is possible to use the predefined function "lexer_text" of the Plexing module. This function just returns the name of the token pattern constructor and its parameter if any.

For example, with this default function, the token symbol IDENT would be written as IDENT in error message (e.g. "IDENT expected"). The "text" function may decide to print it differently, e.g., as "identifier".

tok_comm

Is a mutable field of type:

  option (list location)

It asks the lexer (the lexer function should do it) to record the locations of the comments in the program. Setting this field to "None" indicates that the lexer must not record them. Setting it to "Some []" indicated that the lexer must put the comments location list in the field, which is mutable.

Minimalist version

If a lexer have been written, named "lexer", here is the minimalist version of the value suitable as parameter to "Grammar.gcreate":

  {Plexing.tok_func = lexer;
   Plexing.tok_using _ = (); Plexing.tok_removing _ = ();
   Plexing.tok_match = Plexing.default_match;
   Plexing.tok_text = Plexing.lexer_text;
   Plexing.tok_comm = None}

Functorial interface

The normal interface for grammars described in the previous sections has two drawbacks:

  • First, the type of tokens of the lexers must be "(string * string)"
  • Second, since the entry type has no parameter to specify the grammar it is bound to, there is no static check that entries are compatible, i.e. belong to the same grammar. The check is done at run time.

The functorial interface resolve these two problems. The functor takes a module as parameter where the token type has to be defined, together with the lexer returning streams of tokens of this type. The resulting module define entries compatible the ones to the other, and this is controlled by the OCaml type checker.

The syntax extension must be done with the statement GEXTEND, instead of EXTEND, and deletion by GDELETE_RULE instead of DELETE_RULE.

The lexer type

In the section about the interface with the lexer, we presented the "Plexing.lexer" type as a record without type parameter. Actually, this type is defined as:

  type lexer 'te =
    { tok_func : lexer_func 'te;
      tok_using : pattern -> unit;
      tok_removing : pattern -> unit;
      tok_match : pattern -> 'te -> string;
      tok_text : pattern -> string;
      tok_comm : mutable option (list location) }
  ;

where the type parameter is the type of the token, which can be any type, different from "(string * string)", providing the lexer function (tok_func) returns a stream of this token type and the match function (tok_match) indicates how to match values of this token type against the token patterns (which remain defined as "(string * string)").

Here is an example of an user token type and the associated match function:

  type mytoken =
    [ Ident of string
    | Int of int
    | Comma | Equal
    | Keyw of string  ]
  ;

  value mymatch =
    fun
    [ ("IDENT", "") ->
        fun [ Ident s -> s | _ -> raise Stream.Failure ]
    | ("INT", "") ->
        fun [ Int i -> string_of_int i | _ -> raise Stream.Failure ]
    | ("", ",") ->
        fun [ Comma -> "" | _ -> raise Stream.Failure ]
    | ("", "=") ->
        fun [ Equal -> "" | _ -> raise Stream.Failure ]
    | ("", s) ->
        fun
        [ Keyw k -> if k = s then "" else raise Stream.Failure
        | _ -> raise Stream.Failure ]
    | _ -> raise (Plexing.Error "bad token in match function") ]
  ;

The functor parameter

The type of the functor parameter is defined as:

  module type GLexerType =
    sig
      type te = 'x;
      value lexer : Plexing.lexer te;
    end;

The token type must be specified (type "te") and the lexer also, with the interface for lexers, of the lexer type defined above, the record fields being described in the section "interface with the lexer", but with a general token type.

The resulting grammar module

Once a module of type "GLexerType" has been built (previous section), it is possible to create a grammar module by applying the functor "Grammar.GMake". For example:

  module MyGram = Grammar.GMake MyLexer;

Notice that the function "Entry.parse" of this resulting module does not take a character stream as parameter, but a value of type "parsable". This function is equivalent to the function "parse_parsable" of the non functorial interface. In short, the parsing of some character stream "cs" by some entry "e" of the example grammar above, must be done by:

  MyGram.Entry.parse e (MyGram.parsable cs)

instead of:

  MyGram.Entry.parse e cs

GEXTEND and GDELETE_RULE

The "GEXTEND" and "GDELETE_RULE" statements are also added in the expressions of the OCaml language when the syntax extension kit "pa_extend.cmo" is loaded. They must be used for grammars defined with the functorial interface. Their syntax is:

           expression ::= gextend
                        | gdelete-rule
         gdelete-rule ::= "GDELETE_RULE" gdelete-rule-body "END"
              gextend ::= "GEXTEND" gextend-body "END"
         gextend-body ::= grammar-module-name extend-body
    gdelete-rule-body ::= grammar-module-name delete-rule-body
  grammar-module-name ::= qualid

See the syntax of the EXTEND statement for the meaning of the syntax entries not defined above.

An example: arithmetic calculator

Here is a small calculator of expressions. They are given as parameters of the command.

File "calc.ml":

  #load "pa_extend.cmo";

  value g = Grammar.gcreate (Plexer.gmake ());
  value e = Grammar.Entry.create g "expression";

  EXTEND
    e:
      [ [ x = e; "+"; y = e -> x + y
        | x = e; "-"; y = e -> x - y ]
      | [ x = e; "*"; y = e -> x * y
        | x = e; "/"; y = e -> x / y ]
      | [ x = INT -> int_of_string x
        | "("; x = e; ")" -> x ] ]
    ;
  END;

  open Printf;

  for i = 1 to Array.length Sys.argv - 1 do {
    let r = Grammar.Entry.parse e (Stream.of_string Sys.argv.(i)) in
    printf "%s = %d\n" Sys.argv.(i) r;
    flush stdout;
  };

The link needs the library "gramlib.cma" provided with Camlp5:

  ocamlc -pp camlp5r -I +camlp5 gramlib.cma test/calc.ml -o calc

Examples:

  $ ./calc '239*4649'
  239*4649 = 1111111
  $ ./calc '(47+2)/3'
  (47+2)/3 = 16
camlp5-rel8.00.02/doc/htmlp/html2latex000077500000000000000000000127571410261051500174570ustar00rootroot00000000000000#!/bin/sh # html2latex,v FILES1="index.html strict.html ptools.html" FILES2="parsers.html lexers.html fparsers.html bparsers.html grammars.html" FILES3="printers.html pprintf.html pretty.html" FILES4="locations.html ml_ast.html ast_transi.html ast_strict.html q_ast.html pcaml.html directives.html syntext.html opretty.html redef.html quot.html revsynt.html scheme.html macros.html pragma.html extfun.html" FILES5="commands.html library.html sources.html about.html" VERSION="$(grep "value version =" ../../main/pcaml.ml | sed -e 's/^[^"]*"\([^"]*\).*$/\1/')" FILES="$FILES1 1 $FILES2 2 $FILES3 3 $FILES4 4 $FILES5" /bin/echo '\documentclass[twoside]{report} \marginparwidth 0pt \oddsidemargin 0pt \evensidemargin 0pt \marginparsep 0pt \topmargin 0pt \textwidth 6.5in \textheight 8.5 in \usepackage{longtable} \usepackage{fancyhdr} \usepackage{hyperref} \fancyhead{} \fancyhead[LE,RO]{\leftmark} \newcommand{\clearemptydoublepage}{% \newpage{\pagestyle{empty}\cleardoublepage}} \begin{document} ' /bin/echo "\def\cslversion{$(grep "value version =" ../../main/pcaml.ml | sed -e 's/^[^"]*"\([^"]*\).*$/\1/')}" /bin/echo ' \pagestyle{empty} \begin{center} ~\vfill \Huge Camlp5 - Reference Manual \\ \Large version \cslversion \\[1cm] \large Daniel de Rauglaudre \\ \today \\[1cm] \vfill \normalsize Copyright \copyright\ 2007-2017 Institut National de Recherche en Informatique et Automatique This document was generated by a shell script from the html documentation pages. \end{center} \clearemptydoublepage \setcounter{page}{1} \pagestyle{plain} \tableofcontents' for i in $FILES; do /bin/echo '\clearemptydoublepage' if [ "$i" = "1" ]; then /bin/echo '\part{Parsing tools}' elif [ "$i" = "2" ]; then /bin/echo '\part{Printing tools}' elif [ "$i" = "3" ]; then /bin/echo '\part{Language extensions}' elif [ "$i" = "4" ]; then /bin/echo '\part{Appendix}' /bin/echo '\appendix{}' else cat $i | sed \ -e 's/\\/\\backslash/g' \ -e 's/%/\\%/g' \ -e 's|

]*>|

|g' | sed \ -e '{:b; /<\/p>$/N; s|<\/p>\n *|<\/p>|g; tb}' \ -e 's|

|\n\n\\\n\n\\noindent |g' \ -e '{s/^ *

/\\noindent /; s|

|\n\n|}' | sed \ -e '{/]*>$/N; :b; /$/N; s/\n *//; tb; /<\/tr>$/N; s/\n *//; tb; /<\/th>$/N; s/\n *//; tb; /<\/td>$/N; s/\n *//; tb; /$/N; s/\n *//; tb; /<\/thead>$/N; s/\n *//; tb; /$/N; s/\n *//; tb; /<\/tbody>$/N; s/\n *//; tb}' | sed \ -e 's/{/\\{/g' -e 's/}/\\}/g' \ -e '0,/
/d' \ -e '/
/,/<\/div>/d' \ -e 's/^ *]*>/\\pagestyle{fancy}\\chapter{/' -e 's||}|' \ -e 's/^ *

/\\section{/' -e 's|

|}|' \ -e 's/^ *

/\\subsection{/' -e 's|

|}|' \ -e 's/^ *

/\\subsubsection{/' -e 's|

|}|' \ -e 's/^ *
/\\textbf{/' -e 's|
|}|' \ -e 's| *]*>\(.*\)
|\\begin{center}\n\\begin{tabular}\1\\hline\n\\end{tabular}\n\\end{center}|' \ -e 's| *]*>\(.*\)|\\small\n\\begin{center}\n\\begin{longtable}\1\\hline\n\\end{longtable}\n\\end{center}\\normalsize|' \ -e 's///g' -e 's|||g' \ -e 's///g' -e 's|||g' \ -e 's/\(]*>.*]*>.*]*>\)/{|l|c|l|}\ntr\1/' \ -e 's/\(]*>.*]*>\)/{|l|l|}\ntr\1/' \ -e 's/tr]*class="half"[^>]*>/\\makebox[5.5cm][l]{/g' \ -e 's/]*>/\\makebox[3cm][l]{/g' \ -e 's||} \\\\\n\\hline\n|g' \ -e 's|]*>|{|g' \ -e 's|]*>|} \& {|g' \ -e 's||} \\\\\n|g' \ -e 's|
|\\\\|g' \ -e 's/^ *
    /\\begin{itemize}/' -e 's|^ *
|\\end{itemize}|' \ -e 's/^ *
    /\\begin{enumerate}/' -e 's|^ *
|\\end{enumerate}|' \ -e 's/^ *
  • /\\item /' -e 's| *
  • ||' \ -e 's/^ *
    /\\begin{description}\n\\item[\\ \\ \\ \\ \\ ]/' \ -e 's|
    |\\end{description}|' \ -e 's/^ *]*>/\\begin{description}/' -e 's||\\end{description}|' \ -e 's/^ *
    /\\item[/' -e 's|
    |]|' \ -e 's/^ *
    /\n\\\n\n/' -e 's|
    ||' \ -e 's/^ *]*>/\\begin{verbatim}/' -e 's|^ *|\\end{verbatim}|' \ -e 's//\\texttt{/g' -e 's||}|g' \ -e 's/]*>/\\texttt{/g' -e 's||}|g' \ -e 's//\\emph{/g' -e 's||}|g' \ -e 's//\\emph{/g' -e 's||}|g' \ -e 's//\\textbf{/g' -e 's||}|g' \ -e 's/]*>//g' -e 's|||g' \ -e 's/]*>//g' -e 's|||g' \ -e 's/<//g' -e 's/&/\\\&/g' -e 's/ /\\ /g' \ -e 's/_/\\_/g' \ -e 's/#/\\#/g' \ -e 's/~/\\~{}/g' \ -e 's/\$/\\$/g' \ -e 's/\^/\\^/g' \ -e 's/\\backslash/$\\backslash$/g' \ -e '/\\begin{verbatim}/,/\\end{verbatim}/s/\\_/_/g' \ -e '/\\begin{verbatim}/,/\\end{verbatim}/s/\\#/#/g' \ -e '/\\begin{verbatim}/,/\\end{verbatim}/s/$\\backslash\$/\\/g' \ -e '/\\begin{verbatim}/,/\\end{verbatim}/s/\\\$/$/g' \ -e '/\\begin{verbatim}/,/\\end{verbatim}/s/\\{/{/g' \ -e '/\\begin{verbatim}/,/\\end{verbatim}/s/\\}/}/g' \ -e '/\\begin{verbatim}/,/\\end{verbatim}/s/\\^/^/g' \ -e '/
    /,$d' \ -e 's/]*>/\\noindent /' -e 's|
    ||' \ -e "s||$VERSION|" \ -e '//r ../../LICENSE' -e '//d' fi done /bin/echo '\end{document}' camlp5-rel8.00.02/doc/htmlp/html2texi000077500000000000000000000122731410261051500173040ustar00rootroot00000000000000#!/bin/sh # html2texi,v FILES1="index.html strict.html ptools.html" FILES2="parsers.html lexers.html fparsers.html bparsers.html grammars.html" FILES3="printers.html pprintf.html pretty.html" FILES4="locations.html ml_ast.html ast_transi.html ast_strict.html q_ast.html pcaml.html directives.html syntext.html opretty.html redef.html quot.html revsynt.html scheme.html macros.html pragma.html extfun.html" FILES5="commands.html library.html sources.html about.html" FILES="$FILES1 1 $FILES2 2 $FILES3 3 $FILES4 4 $FILES5" VERSION="$(grep "value version =" ../../main/pcaml.ml | sed -e 's/^[^"]*"\([^"]*\).*$/\1/')" /bin/echo '\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename camlp5.info' /bin/echo "@settitle Camlp5 manual $VERSION" /bin/echo '@c %**end of header' /bin/echo ' @titlepage @title Camlp5 manual @author Daniel de Rauglaudre @end titlepage' /bin/echo ' @node Top @top Camlp5: a preprocessor pretty printer for OCaml' /bin/echo "@noindent Version $VERSION" /bin/echo ' @menu' ( /bin/echo 'sed \' for i in $FILES; do if [ "$i" = "1" ]; then : elif [ "$i" = "2" ]; then : elif [ "$i" = "3" ]; then : elif [ "$i" = "4" ]; then : elif [ "$i" = "5" ]; then : else N=$(grep ']*>||' -e 's|||') /bin/echo " -e 's/@pxref{$i}/@pxref{$N}/' \\" fi done /bin/echo ) > tmp for i in $FILES; do if [ "$i" = "1" ]; then /bin/echo /bin/echo 'Parsing Tools' /bin/echo elif [ "$i" = "2" ]; then /bin/echo /bin/echo 'Printing Tools' /bin/echo elif [ "$i" = "3" ]; then /bin/echo /bin/echo 'Language extensions' /bin/echo elif [ "$i" = "4" ]; then /bin/echo /bin/echo 'Appendix' /bin/echo else N=$(grep ']*>||' -e 's|||') /bin/echo "* $N::" fi done /bin/echo ' @end menu' /bin/echo chapter=chapter for i in $FILES; do if [ "$i" = "1" ]; then : elif [ "$i" = "2" ]; then : elif [ "$i" = "3" ]; then : elif [ "$i" = "4" ]; then : elif [ "$i" = "5" ]; then chapter=appendix else N=$(grep ']*>||' -e 's|||') /bin/echo " @node $N @$chapter $N" cat $i | sed \ -e 's|^\(.*\)
    ' ) > toc.tmp cat $FILE | sed \ -e '/title="Normal"/a \ ' | sed \ -e '/