Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 15d4ac4853ddceb54c8d74e8c6e99bb2 > files > 26

ocaml-camlp5-doc-5.12-1mdv2010.0.i586.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <!-- $Id: printers.html 1911 2008-08-02 02:32:13Z deraugla $ -->
  <!-- Copyright (c) 2007-2008 INRIA -->
  <title>extensible printers</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <link rel="stylesheet" type="text/css" href="styles/base.css"
        title="Normal" />
  <link rel="alternate" type="application/rss+xml" href="rss/camlp5.rss" 
        title="Camlp5"/>
</head>
<body>

<div id="menu">
  <h1>- <a href="http://pauillac.inria.fr/~ddr/camlp5">Camlp5</a> -</h1>
  <p class="subtitle">Version 5.11</p>
  <ul>
    <li><a href="index.html">Introduction</a></li>
    <li><a href="strict.html">Transitional and Strict</a></li>
    <li><a href="ptools.html">Parsing and printing tools</a></li>
  </ul>
  <ul>
    <li>Parsing tools
      <ul>
        <li><a href="parsers.html">Stream parsers</a></li>
        <li><a href="lexers.html">Stream lexers</a></li>
        <li><a href="fparsers.html">Functional parsers</a></li>
        <li><a href="bparsers.html">Backtracking parsers</a></li>
        <li><a href="grammars.html">Extensible grammars</a></li>
      </ul>
    </li>
    <li>Printing tools
      <ul>
        <li><a href="printers.html">Extensible printers</a></li>
        <li><a href="pprintf.html">Pprintf</a></li>
        <li><a href="pretty.html">Pretty print</a></li>
      </ul>
    </li>
    <li>Language extensions
      <ul>
        <li><a href="locations.html">Locations</a></li>
        <li><a href="ml_ast.html">Syntax tree</a></li>
        <li><a href="ast_transi.html">Syntax tree - transi</a></li>
        <li><a href="ast_strict.html">Syntax tree - strict</a></li>
        <li><a href="q_ast.html">Quotation kit q_ast.cmo</a></li>
        <li><a href="pcaml.html">The Pcaml module</a></li>
        <li><a href="syntext.html">Extensions of syntax</a></li>
        <li><a href="opretty.html">Extensions of printing</a></li>
        <li><a href="quot.html">Quotations</a></li>
        <li><a href="revsynt.html">Revised syntax</a></li>
        <li><a href="scheme.html">Scheme syntax</a></li>
        <li><a href="macros.html">Macros</a></li>
        <li><a href="pragma.html">Pragma directive</a></li>
        <li><a href="extfun.html">Extensible functions</a></li>
      </ul>
    </li>
    <li>Appendix
      <ul>
        <li><a href="commands.html">Commands and Files</a></li>
        <li><a href="library.html">Library</a></li>
        <li><a href="sources.html">Camlp5 sources</a></li>
        <li><a href="about.html">About Camlp5</a></li>
      </ul>
    </li>
  </ul>
</div>

<div id="content">

<h1 class="top">Extensible printers</h1>

<p>This chapter describes the syntax and semantics of the extensible
  printers of Camlp5.</p>

<p>Similar to the <a href="grammars.html">extensible grammars</a>, the
  extensible printers allow to define and extend printers of data or
  programs. A specific statement "<tt>EXTEND_PRINTER</tt>" allow to
  define these extensions.</p>

<div id="tableofcontents">
  <ol>
    <li><a href="#a:Getting-started">Getting started</a></li>
    <li><a href="#a:Syntax-of-the-EXTEND_PRINTER-statement">Syntax of the EXTEND_PRINTER statement</a></li>
    <li><a href="#a:Semantics-of-EXTEND_PRINTER">Semantics of EXTEND_PRINTER</a>
      <ul>
        <li><a href="#b:Printers-definition-list">Printers definition list</a></li>
        <li><a href="#b:Rules-insertion">Rules insertion</a></li>
        <li><a href="#b:Semantic-action">Semantic action</a></li>
      </ul>
    </li>
    <li><a href="#a:The-Eprinter-module">The Eprinter module</a></li>
    <li><a href="#a:Examples">Examples</a>
      <ul>
        <li><a href="#b:Parser-and-Printer-of-expressions">Parser and Printer of expressions</a></li>
        <li><a href="#b:Printing-OCaml-programs">Printing OCaml programs</a></li>
      </ul>
    </li>
  </ol>
</div>

<h2 id="a:Getting-started">Getting started</h2>

<p>A printer is a value of type "<tt>Eprinter.t a</tt>" where
  "<tt>a</tt>" is the type of the item to be printed. When applied, a
  printer returns a string, representing the printed item.</p>

<p>To create a printer, one must use the function
  "<tt>Eprinter.make</tt>" with, as parameter, the name of the
  printer, (used in error messages). A printer is created empty,
  i.e. it fails if it is applied.</p>

<p>As with grammar entries, printers may have several levels. When the
  function "<tt>Eprinter.apply</tt>" is applied to a printer, the
  first level is called.  The function "<tt>Eprinter.apply_level</tt>"
  allows to call a printer at some specific level possibly different
  from the first one. When a level does not match any value of the
  printed item, the next level is tested. If there is no more levels,
  the printer fails.</p>

<p>In semantic actions of printers, functions are provided to
  recursively call the current level and the next level. Moreover,
  a <em>printing context</em> variable is also given, giving the
  current indentation, what should be printed before in the same line
  and what should be printed after in the same line (it is not
  mandatory to use them).</p>

<p>The extension of printers can be done with the
  "<tt>EXTEND_PRINTER</tt>" statement added by the <em>parsing
  kit</em> "<tt>pa_extprint.cmo</tt>".</p>

<h2 id="a:Syntax-of-the-EXTEND_PRINTER-statement">Syntax of the EXTEND_PRINTER statement</h2>

<pre>
        expression ::= extend-statement
  extend-statement ::= "EXTEND_PRINTER" extend-body "END"
       extend-body ::= extend-printers
   extend-printers ::= extend-printer extend-printers
                     | &lt;nothing&gt;
    extend-printer ::= printer-name ":" position-opt "[" levels "]"
      position-opt ::= "FIRST"
                     | "LAST"
                     | "BEFORE" label
                     | "AFTER" label
                     | "LEVEL" label
                     | &lt;nothing&gt;
            levels ::= level "|" levels
                     | level
             level ::= label-opt "[" rules "]"
         label-opt ::= label
                     | &lt;nothing&gt;
             rules ::= rule "|" rules
                     | rule
              rule ::= pattern "->" expression
                     | pattern "when" expression "->" expression
      printer-name ::= qualid
            qualid ::= qualid "." qualid
                     | uident
                     | lident
            uident ::= 'A'-'Z' ident
            lident ::= ('a'-'z' | '_' | misc-byte) ident
             ident ::= ident-char*
        ident-char ::= ('a'-'a' | 'A'-'Z' | '0'-'9' | '_' | ''' | misc-byte)
         misc-byte ::= '\128'-'\255'
</pre>

<h2 id="a:Semantics-of-EXTEND_PRINTER">Semantics of EXTEND_PRINTER</h2>

<h3 id="b:Printers-definition-list">Printers definition list</h3>

<p>All printers are extended according to their corresponding
  definitions which start with an optional "position" and follow with
  the "levels" definition.</p>

<h4>Optional position</h4>

<p>After the colon, it is possible to specify where to insert the
  defined levels:</p>

<ul>
  <li>The identifier "<tt>FIRST</tt>" (resp. "<tt>LAST</tt>")
    indicates that the level must be inserted before (resp. after) all
    possibly existing levels of the entry. They become their first
    (resp. last) levels.</li>
  <li>The identifier "<tt>BEFORE</tt>" (resp. "<tt>AFTER</tt>")
    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.</li>
  <li>The identifier "<tt>LEVEL</tt>" followed by a 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.</li>
  <li>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).</li>
</ul>

<h4>Levels</h4>

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

<p>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 <em>position</em> (see previous section) or
  for possible direct calls to this specific level.</p>

<h4>Rules</h4>

<p>A level is a list of <em>rules</em> separated by vertical bars, the
  whole list being between brackets.</p>

<p>A rule is an usual pattern association (in a function or in the
  "match" statement), i.e. a pattern, an arrow and an expression. The
  expression is the semantic action which must be of type
  "<tt>string</tt>".</p>

<h3 id="b:Rules-insertion">Rules insertion</h3>

<p>The rules are sorted by their patterns, according to the rules of
  the <a href="extfun.html">extensible functions</a>.</p>

<h3 id="b:Semantic-action">Semantic action</h3>

<p>The semantic action, i.e. the expression following the right arrow
  in rules, contains in its environment the variables bound by the
  pattern and three more variables:</p>

<ul>
  <li>The variable "<tt>curr</tt>" which is a function which can be
    called to recursively invoke the printer at the current
    level,</li>
  <li>The variable "<tt>next</tt>" which is a function which can be
    called to invoke the printer at the next level,</li>
  <li>The variable "<tt>pc</tt>" which contains the printing context
    of type "<tt>Pprintf.pr_context</tt>" (see
    chapter <a href="pprintf.html">Pprintf</a>).</li>
</ul>

<p>The variables "<tt>curr</tt>" and "<tt>next</tt>" are of type:</p>

<pre>
  pr_context -> t -> string
</pre>

<p>where "<tt>t</tt>" is the type of the printer (i.e. the type of its
  patterns).</p>

<p>The variable "<tt>curr</tt>", "<tt>next</tt>" and "<tt>pc</tt>"
  have predefined names and can hide the possible identifiers having
  the same names in the pattern or in the environment of the
  "<tt>EXTEND_PRINTER</tt>" statement.</p>

<h2 id="a:The-Eprinter-module">The Eprinter module</h2>

<p>See its <a href="library.html#a:Eprinter-module">section</a> in the
  chapter "Library".</p>

<h2 id="a:Examples">Examples</h2>

<h3 id="b:Parser-and-Printer-of-expressions">Parser and Printer of expressions</h3>

<p>This example illustrates the symmetry between parsers and
  printers. A simple type of expressions is defined. A parser converts
  a string to a value of this type, and a printer converts a value of
  this type to a string.</p>

<p>In the printer, there is no use of the "<tt>pc</tt>" parameter and
  no use of the "<tt>Pretty</tt>" module. The strings are printed on
  a single line.</p>

<p>Here is the source (file "<tt>foo.ml</tt>"):</p>

<pre>
  #load "pa_extend.cmo";
  #load "pa_extprint.cmo";

  open Printf;

  type expr =
    [ Op of string and expr and expr
    | Int of int
    | Var of string ]
  ;

  value g = Grammar.gcreate (Plexer.gmake ());
  value pa_e = Grammar.Entry.create g "expr";
  value pr_e = Eprinter.make "expr";

  EXTEND
    pa_e:
      [ [ x = SELF; "+"; y = SELF -> Op "+" x y
        | x = SELF; "-"; y = SELF -> Op "-" x y ]
      | [ x = SELF; "*"; y = SELF -> Op "*" x y
        | x = SELF; "/"; y = SELF -> Op "/" x y ]
      | [ x = INT -> Int (int_of_string x)
        | x = LIDENT -> Var x
        | "("; x = SELF; ")" -> x ] ]
    ;
  END;

  EXTEND_PRINTER
    pr_e:
      [ [ Op "+" x y -> sprintf "%s + %s" (curr pc x) (next pc y)
        | Op "-" x y -> sprintf "%s - %s" (curr pc x) (next pc y) ]
      | [ Op "*" x y -> sprintf "%s * %s" (curr pc x) (next pc y)
        | Op "/" x y -> sprintf "%s / %s" (curr pc x) (next pc y) ]
      | [ Int x -> string_of_int x
        | Var x -> x
        | x -> sprintf "(%s)" (Eprinter.apply pr_e pc x) ] ]
    ;
  END;

  value parse s = Grammar.Entry.parse pa_e (Stream.of_string s);
  value print e = Eprinter.apply pr_e Eprinter.empty_pc e;

  if Sys.interactive.val then ()
  else print_endline (print (parse Sys.argv.(1)));
</pre>

<p>Remark on the use of "curr" and "next" while printing operators:
  due to left associativity, the first operand uses "curr" and the
  second operand uses "next". For right associativity operators, they
  should be inverted. For no associativity, both should use
  "next".</p>

<p>The last line of the file allows use in either the OCaml toplevel
  or as standalone program, taking the string to be printed as
  parameter. It can be compiled this way:</p>

<pre>
  ocamlc -pp camlp5r -I +camlp5 gramlib.cma foo.ml
</pre>

<p>Examples of use (notice the redundant parentheses automatically
  removed by the printing algorithm):</p>

<pre>
  $ ./a.out "(3 * x) + (2 / y)"
  3 * x + 2 / y
  $ ./a.out "(x+y)*(x-y)"
  (x + y) * (x - y)
  $ ./a.out "x + y - z"
  x + y - z
  $ ./a.out "(x + y) - z"
  x + y - z
  $ ./a.out "x + (y - z)"
  x + (y - z)
</pre>

<h3 id="b:Printing-OCaml-programs">Printing OCaml programs</h3>

<p>Complete examples of usage of extensible printers are the printers
  in syntaxes and extended syntaxes provided by Camlp5 in the pretty
  printing <em>kits</em>:</p>

<ul>
  <li><tt>pr_r.cmo</tt>: pretty print in revised syntax</li>
  <li><tt>pr_o.cmo</tt>: pretty print in normal syntax</li>
  <li><tt>pr_rp.cmo</tt>: also pretty print the parsers in revised
    syntax</li>
  <li><tt>pr_op.cmo</tt>: also pretty print the parsers in normal
    syntax</li>
</ul>

<p>See the chapter entitled "<a href="opretty.html">Printing
  programs</a>".</p>

<a class="toplink" href="printers.html">↑</a>
<div class="trailer">

  <hr style="margin:0" /><div style="font-size: 80%"><em>Copyright 2007
      Daniel de Rauglaudre (INRIA)</em></div>

  <p class="bottom">
    <a href="http://validator.w3.org/check?uri=referer"><img
       src="images/valid-xhtml11.png" style="border:0"
       alt="Valid XHTML 1.1" height="31" width="88" /></a>
  </p>

</div>

</div>

</body>
</html>