Sophie

Sophie

distrib > Fedora > 13 > i386 > media > os > by-pkgid > 19c0846d50c5b0d671ee1dea8e95ddee > files > 40

python-cly-0.9-2.fc12.i686.rpm

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
<title>CLY Developer's Guide</title>
<style type="text/css">

.highlight .c { color: #008800; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #008800 } /* Comment.Preproc */
.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */
.highlight .cs { color: #008800; font-weight: bold } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */
.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #AA22FF; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BB4444 } /* Literal.String */
.highlight .na { color: #BB4444 } /* Name.Attribute */
.highlight .nb { color: #AA22FF } /* Name.Builtin */
.highlight .nc { color: #0000FF } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #00A000 } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #B8860B } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */
.highlight .sc { color: #BB4444 } /* Literal.String.Char */
.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BB4444 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BB4444 } /* Literal.String.Single */
.highlight .ss { color: #B8860B } /* Literal.String.Symbol */
.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */
.highlight .vc { color: #B8860B } /* Name.Variable.Class */
.highlight .vg { color: #B8860B } /* Name.Variable.Global */
.highlight .vi { color: #B8860B } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */

/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:Date: $Date$
:Revision: $Revision$
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left {
  clear: left }

img.align-right {
  clear: right }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #eeeeee }

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

tt.docutils {
  background-color: #eeeeee }

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="cly-developer-s-guide">
<h1 class="title">CLY Developer's Guide</h1>

<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#overview" id="id1">Overview</a></li>
<li><a class="reference internal" href="#experimenting" id="id2">Experimenting</a></li>
<li><a class="reference internal" href="#building-a-grammar-from-python" id="id3">Building a Grammar from Python</a><ul>
<li><a class="reference internal" href="#matching-input" id="id4">Matching Input</a></li>
<li><a class="reference internal" href="#grammar-branching" id="id5">Grammar Branching</a></li>
<li><a class="reference internal" href="#collecting-variables" id="id6">Collecting Variables</a></li>
<li><a class="reference internal" href="#variable-types" id="id7">Variable Types</a></li>
<li><a class="reference internal" href="#executing-callbacks" id="id8">Executing Callbacks</a></li>
<li><a class="reference internal" href="#implementing-custom-completion" id="id9">Implementing Custom Completion</a></li>
<li><a class="reference internal" href="#adding-help" id="id10">Adding Help</a></li>
<li><a class="reference internal" href="#types-of-nodes" id="id11">Types of Nodes</a></li>
<li><a class="reference internal" href="#node-attributes-and-constructor-arguments" id="id12">Node Attributes and Constructor Arguments</a></li>
<li><a class="reference internal" href="#context" id="id13">Context</a></li>
</ul>
</li>
<li><a class="reference internal" href="#defining-a-grammar-in-xml" id="id14">Defining a Grammar in XML</a><ul>
<li><a class="reference internal" href="#parsing-an-xml-grammar" id="id15">Parsing an XML Grammar</a></li>
<li><a class="reference internal" href="#xml-attribute-type-conversion" id="id16">XML Attribute Type Conversion</a></li>
</ul>
</li>
<li><a class="reference internal" href="#parsing" id="id17">Parsing</a><ul>
<li><a class="reference internal" href="#parse-context" id="id18">Parse Context</a></li>
<li><a class="reference internal" href="#passing-user-defined-objects-to-callbacks" id="id19">Passing User-defined Objects to Callbacks</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="overview">
<h1><a class="toc-backref" href="#id1">Overview</a></h1>
<p>CLY provides a convenient means to easily build command-line interfaces. This is
achieved by defining a CLY grammar in either Python or XML then constructing a
CLY parser object from the grammar. The parser parses user input against the
grammar, executes callbacks, provides completion, and so on.</p>
<p>A built-in terminal interface based on readline is provided.</p>
</div>
<div class="section" id="experimenting">
<h1><a class="toc-backref" href="#id2">Experimenting</a></h1>
<p>The quickest way to experiment with CLY is by passing a <tt class="docutils literal"><span class="pre">Grammar</span></tt> or
<tt class="docutils literal"><span class="pre">Parser</span></tt> object to the <tt class="docutils literal"><span class="pre">interact</span></tt> function:</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">cly</span> <span class="kn">import</span> <span class="n">interact</span>

<span class="n">interact</span><span class="p">(</span><span class="n">grammar_or_parser</span><span class="p">)</span>
</pre></div>
<p>This will start a readline console using the given grammar. Press <tt class="docutils literal"><span class="pre">?</span></tt> at any
time for contextual help, <tt class="docutils literal"><span class="pre">&lt;Tab&gt;</span></tt> to attempt completion, and <tt class="docutils literal"><span class="pre">&lt;Ctrl-D&gt;</span></tt>
(EOF) on an empty line to terminate the shell.</p>
<p>Now, on with the nitty gritty.</p>
</div>
<div class="section" id="building-a-grammar-from-python">
<h1><a class="toc-backref" href="#id3">Building a Grammar from Python</a></h1>
<div class="section" id="matching-input">
<h2><a class="toc-backref" href="#id4">Matching Input</a></h2>
<p>The syntax of a shell is defined as a tree of <tt class="docutils literal"><span class="pre">Node</span></tt> objects.  Each node
matches a token of user input defined by the <tt class="docutils literal"><span class="pre">pattern</span></tt> attribute of the
<tt class="docutils literal"><span class="pre">Node</span></tt> and defaults to the <tt class="docutils literal"><span class="pre">Node</span></tt> name. <tt class="docutils literal"><span class="pre">pattern</span></tt> is treated a regular
expression. For example, the following grammar would match the token <tt class="docutils literal"><span class="pre">one</span></tt>:</p>
<div class="highlight"><pre><span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
  <span class="n">one</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;One&#39;</span><span class="p">)</span>
<span class="p">)</span>
</pre></div>
<p>Because nodes are hierarchical, child nodes are only considered for
matching after the parent has matched and consumed a token. The
following grammar would match the tokens <tt class="docutils literal"><span class="pre">parent</span> <span class="pre">child</span></tt>:</p>
<div class="highlight"><pre><span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
  <span class="n">parent</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Parent&#39;</span><span class="p">)(</span>
    <span class="n">child</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Child&#39;</span><span class="p">)</span>
  <span class="p">)</span>
<span class="p">)</span>
</pre></div>
<p>As mentioned, the name of the node is used as the default pattern to
match against input tokens. This can be overridden by passing
<tt class="docutils literal"><span class="pre">pattern=&lt;regex&gt;</span></tt> to the constructor. The following example will match
one or more digits:</p>
<div class="highlight"><pre><span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
  <span class="n">number</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Number&#39;</span><span class="p">,</span> <span class="n">pattern</span><span class="o">=</span><span class="s">r&#39;\d+&#39;</span><span class="p">),</span>
<span class="p">)</span>
</pre></div>
</div>
<div class="section" id="grammar-branching">
<h2><a class="toc-backref" href="#id5">Grammar Branching</a></h2>
<p>It's a common requirement that paths in the grammar be executed
multiple times, whether that be to enter a list of IP addresses, allow
multiple commands at a branch, etc. In CLY this is achieved with the
<tt class="docutils literal"><span class="pre">Alias</span></tt> node. An alias node, as its name suggests, aliases its target
at the current location, effectively merging two branches of the
grammar.</p>
<p>Here's an example:</p>
<div class="highlight"><pre><span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
  <span class="n">one</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;One&#39;</span><span class="p">)(</span>
    <span class="n">Alias</span><span class="p">(</span><span class="s">&#39;/three&#39;</span><span class="p">),</span>
    <span class="n">two</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Two&#39;</span><span class="p">)(</span>
    <span class="p">)</span>
  <span class="p">),</span>
  <span class="n">three</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Three&#39;</span><span class="p">),</span>
<span class="p">)</span>
</pre></div>
<p>This will alias the node <tt class="docutils literal"><span class="pre">/three</span></tt> underneath <tt class="docutils literal"><span class="pre">/one</span></tt>. That is, this
grammar will match the input <tt class="docutils literal"><span class="pre">one</span> <span class="pre">three</span></tt>.</p>
<p>Nodes are referenced by their full or relative path, and globs may be
used to alias multiple nodes at once. The following example will alias
everything at <tt class="docutils literal"><span class="pre">/three/*</span></tt>, underneath <tt class="docutils literal"><span class="pre">/one/</span></tt>:</p>
<div class="highlight"><pre><span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
  <span class="n">one</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;One&#39;</span><span class="p">)(</span>
    <span class="n">Alias</span><span class="p">(</span><span class="s">&#39;../../three/*&#39;</span><span class="p">),</span>
    <span class="n">two</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Two&#39;</span><span class="p">),</span>
  <span class="p">),</span>
  <span class="n">three</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Three&#39;</span><span class="p">)(</span>
    <span class="n">four</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Four&#39;</span><span class="p">),</span>
    <span class="n">five</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Five&#39;</span><span class="p">),</span>
  <span class="p">),</span>
<span class="p">)</span>
</pre></div>
<p>By default, nodes may only be traversed once per parse run. This can be
overridden by passing <tt class="docutils literal"><span class="pre">traversals=&lt;count&gt;</span></tt> to node constructors. If
<tt class="docutils literal"><span class="pre">traversals</span> <span class="pre">==</span> <span class="pre">0</span></tt> then there are no limits set. If <tt class="docutils literal"><span class="pre">traversals</span> <span class="pre">&gt;</span> <span class="pre">1</span></tt>
then <em>the variable will be stored as a list</em>.</p>
</div>
<div class="section" id="collecting-variables">
<h2><a class="toc-backref" href="#id6">Collecting Variables</a></h2>
<p>Matching input is great, but if you want your grammar to be useful
you're going to want it to do something with it. This is where the
<tt class="docutils literal"><span class="pre">Variable</span></tt> class comes in: it stores matching input tokens into the
parse context for later use as arguments to execution callbacks.</p>
<p>Here's an example of a variable matching a number:</p>
<div class="highlight"><pre><span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
  <span class="n">number</span><span class="o">=</span><span class="n">Variable</span><span class="p">(</span><span class="s">&#39;Number&#39;</span><span class="p">,</span> <span class="n">pattern</span><span class="o">=</span><span class="s">r&#39;\d+&#39;</span><span class="p">),</span>
<span class="p">)</span>
</pre></div>
<p>The matched input token is stored by the <tt class="docutils literal"><span class="pre">Variable.selected()</span></tt> method,
into the <tt class="docutils literal"><span class="pre">vars</span></tt> dictionary of the context.</p>
<p>When parsing terminates on an action, the context variables are passed
as keyword arguments to the final callback. For example, given the input
<tt class="docutils literal"><span class="pre">1234</span></tt> the above grammar would execute the callback with
<tt class="docutils literal"><span class="pre">callback(number='1234')</span></tt></p>
<p>It's as simple as that.</p>
</div>
<div class="section" id="variable-types">
<h2><a class="toc-backref" href="#id7">Variable Types</a></h2>
<p>By default, variables are passed to callbacks as strings. Having to then
manually convert these arguments to whatever type you want would be
tedious, so CLY allows end users to customise the value passed to the
callback by subclassing <tt class="docutils literal"><span class="pre">Variable</span></tt> and overriding the <tt class="docutils literal"><span class="pre">parse()</span></tt>
method. The default behaviour for this method is to pass all matching
input text as a string.</p>
<p>Continuing the example from the previous section:</p>
<div class="highlight"><pre><span class="k">class</span> <span class="nc">Number</span><span class="p">(</span><span class="n">Variable</span><span class="p">):</span>

  <span class="n">pattern</span> <span class="o">=</span> <span class="s">r&#39;\d+&#39;</span>

  <span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="n">match</span><span class="p">):</span>
    <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">())</span>
</pre></div>
<p>Where <tt class="docutils literal"><span class="pre">context</span></tt> is a <tt class="docutils literal"><span class="pre">cly.parser.Context</span></tt> object and <tt class="docutils literal"><span class="pre">match</span></tt> is a
<tt class="docutils literal"><span class="pre">re.Match</span></tt> object.</p>
<p>Now our callback will be executed with <tt class="docutils literal"><span class="pre">callback(number=1234)</span></tt>. Of
course, much more complex conversions can occur, including IP address
parsing, E-Mail parsing, etc. A set of commonly used variable types is
included in <tt class="docutils literal"><span class="pre">cly.builder</span></tt>.</p>
<p>Note how the <tt class="docutils literal"><span class="pre">pattern</span></tt> attribute may be a class member as a convenience.</p>
</div>
<div class="section" id="executing-callbacks">
<h2><a class="toc-backref" href="#id8">Executing Callbacks</a></h2>
<p>Now that we have collected variables from the user into our context, we
want to execute a callback with those variables. This is achieved with
the <tt class="docutils literal"><span class="pre">Action</span></tt> node and matches the end of input.</p>
<p>Here's an example:</p>
<div class="highlight"><pre><span class="k">def</span> <span class="nf">print_number</span><span class="p">(</span><span class="n">number</span><span class="p">):</span>
  <span class="k">print</span> <span class="n">number</span>

<span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
  <span class="n">number</span><span class="o">=</span><span class="n">Number</span><span class="p">(</span><span class="s">&#39;A number&#39;</span><span class="p">)(</span>
    <span class="n">Action</span><span class="p">(</span><span class="s">&#39;Print number&#39;</span><span class="p">,</span> <span class="n">print_number</span><span class="p">),</span>
  <span class="p">)</span>
<span class="p">)</span>
</pre></div>
<p>In addition to all of the attributes included with <tt class="docutils literal"><span class="pre">Node</span></tt>, <tt class="docutils literal"><span class="pre">Action</span></tt> also has
the <tt class="docutils literal"><span class="pre">with_user_context</span></tt> flag. This can be used to pass a user-defined context
variable (as opposed to the parser context) to the callback as the first
argument. Refer to <a class="reference internal" href="#passing-user-defined-objects-to-callbacks">Passing User-defined Objects to Callbacks</a> for more
information about user contexts.</p>
</div>
<div class="section" id="implementing-custom-completion">
<h2><a class="toc-backref" href="#id9">Implementing Custom Completion</a></h2>
<p>To implement your own custom completion, override <tt class="docutils literal"><span class="pre">Node.candidates(context,</span>
<span class="pre">text)</span></tt>. This can be achieved by passing <tt class="docutils literal"><span class="pre">candidates=&lt;callable&gt;</span></tt> to the
<tt class="docutils literal"><span class="pre">Node</span></tt> constructor or by normal subclassing. Unless <tt class="docutils literal"><span class="pre">match_candidates=True</span></tt>
though, the node will still match any input that matches its <tt class="docutils literal"><span class="pre">pattern</span></tt>.
Setting this flag to <tt class="docutils literal"><span class="pre">False</span></tt> will constrain the node to only match valid
candidates.</p>
<p>The <cite>canidates()</cite> method itself must return a list of strings <em>with trailing
whitespace</em> that match the <tt class="docutils literal"><span class="pre">text</span></tt> argument. <tt class="docutils literal"><span class="pre">context</span></tt> is a parser context
object, described elsewhere.</p>
<p>Here's an example of how one could implement a kill command:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">signal</span>
<span class="kn">from</span> <span class="nn">cly</span> <span class="kn">import</span> <span class="o">*</span>

<span class="c"># Build dictionary of signal_name:signal</span>
<span class="n">signals</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">([(</span><span class="n">s</span><span class="p">[</span><span class="mf">3</span><span class="p">:],</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">signal</span><span class="p">,</span> <span class="n">s</span><span class="p">))</span>
                <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="nb">dir</span><span class="p">(</span><span class="n">signal</span><span class="p">)</span>
                <span class="k">if</span> <span class="n">s</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;SIG&#39;</span><span class="p">)</span>
                   <span class="ow">and</span> <span class="ow">not</span> <span class="n">s</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;SIG_&#39;</span><span class="p">)])</span>

<span class="k">def</span> <span class="nf">complete_signals</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">text</span><span class="p">):</span>
  <span class="k">return</span> <span class="p">[</span><span class="n">s</span> <span class="o">+</span> <span class="s">&#39; &#39;</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">signals</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span> <span class="k">if</span> <span class="n">s</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">text</span><span class="p">)]</span>

<span class="k">def</span> <span class="nf">kill</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">signal</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
  <span class="k">try</span><span class="p">:</span>
    <span class="n">os</span><span class="o">.</span><span class="n">kill</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">signals</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">signal</span><span class="p">,</span> <span class="n">signals</span><span class="p">[</span><span class="s">&#39;TERM&#39;</span><span class="p">]))</span>
  <span class="k">except</span> <span class="ne">OSError</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
    <span class="k">print</span> <span class="s">&#39;error:&#39;</span><span class="p">,</span> <span class="n">e</span>

<span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
  <span class="n">kill</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span>
    <span class="n">pid</span><span class="o">=</span><span class="n">Integer</span><span class="p">(</span><span class="s">&#39;PID to kill&#39;</span><span class="p">)(</span>
      <span class="n">action</span><span class="o">=</span><span class="n">Action</span><span class="p">(</span><span class="s">&#39;Send signal&#39;</span><span class="p">,</span> <span class="n">kill</span><span class="p">),</span>
      <span class="n">signal</span><span class="o">=</span><span class="n">Variable</span><span class="p">(</span><span class="s">&#39;Signal to send to process&#39;</span><span class="p">,</span>
                      <span class="n">candidates</span><span class="o">=</span><span class="n">complete_signals</span><span class="p">,</span>
                      <span class="n">match_candidates</span><span class="o">=</span><span class="bp">True</span><span class="p">)(</span>
          <span class="n">Alias</span><span class="p">(</span><span class="s">&#39;/kill/pid/action&#39;</span><span class="p">),</span>
        <span class="p">),</span>
      <span class="p">),</span>
    <span class="p">),</span>
  <span class="p">)</span>

<span class="n">interact</span><span class="p">(</span><span class="n">grammar</span><span class="p">)</span>
</pre></div>
</div>
<div class="section" id="adding-help">
<h2><a class="toc-backref" href="#id10">Adding Help</a></h2>
<p>The first argument to every CLY grammar node <strong>must</strong> be either a help string
or a callable that returns an iterable of <tt class="docutils literal"><span class="pre">(key,</span> <span class="pre">help)</span></tt> tuples. This is used
to construct contextual help when a user presses <cite>?</cite>.</p>
<p>In the vast majority of cases a simple string, or possibly a pair, will be sufficient.
For when it is not, the convenience class <tt class="docutils literal"><span class="pre">cly.parser.Help</span></tt> is available to
construct help, either from a single pair:</p>
<div class="highlight"><pre><span class="n">one</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="n">Help</span><span class="o">.</span><span class="n">pair</span><span class="p">(</span><span class="s">&#39;one&#39;</span><span class="p">,</span> <span class="s">&#39;Command 1&#39;</span><span class="p">))</span>
</pre></div>
<p>or from a list of tuples:</p>
<div class="highlight"><pre><span class="n">help</span> <span class="o">=</span> <span class="p">[(</span><span class="s">&#39;one&#39;</span><span class="p">,</span> <span class="s">&#39;Command 1&#39;</span><span class="p">),</span>
        <span class="p">(</span><span class="s">&#39;1&#39;</span><span class="p">,</span> <span class="s">&#39;Command 1&#39;</span><span class="p">)]</span>

<span class="n">one</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="n">Help</span><span class="p">(</span><span class="n">help</span><span class="p">),</span> <span class="n">pattern</span><span class="o">=</span><span class="s">r&#39;one|1&#39;</span><span class="p">)</span>
</pre></div>
</div>
<div class="section" id="types-of-nodes">
<h2><a class="toc-backref" href="#id11">Types of Nodes</a></h2>
<p>CLY includes a whole suite of builtin node types, which can be broken down into
the following groups:</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">Node</span></tt></dt>
<dd>The base grammar node. These nodes in the grammar are purely for
routing the grammar to other nodes. They have no side-effects.</dd>
<dt><tt class="docutils literal"><span class="pre">Grammar</span></tt></dt>
<dd>The root of the grammar. Contains all other nodes and acts purely as a
container and a match for the beginning of input.</dd>
<dt><tt class="docutils literal"><span class="pre">Group</span></tt></dt>
<dd>A convenience class used to apply attributes to a group of nodes.</dd>
<dt><tt class="docutils literal"><span class="pre">Alias</span></tt></dt>
<dd>Allow branches of the grammar to be included in other locations. The only
argument to <tt class="docutils literal"><span class="pre">Alias</span></tt> is the relative or absolute path of the branch to be
included. This path can take the form of a glob in order to include
multiple nodes. Use this to create optional arguments.</dd>
<dt><tt class="docutils literal"><span class="pre">Variable</span></tt></dt>
<dd>Variable nodes insert their matching input into the <tt class="docutils literal"><span class="pre">vars</span></tt> dictionary of
the <tt class="docutils literal"><span class="pre">Context</span></tt>, after being parsed by the <tt class="docutils literal"><span class="pre">parse()</span></tt> method. If the
<tt class="docutils literal"><span class="pre">Variable</span></tt> attribute <tt class="docutils literal"><span class="pre">traversals</span></tt> is not 1, values are collected into a
list rather than a scalar.  CLY includes a number of potentially useful
<tt class="docutils literal"><span class="pre">Variable</span></tt> subclasses such as <tt class="docutils literal"><span class="pre">URI</span></tt>, <tt class="docutils literal"><span class="pre">Integer</span></tt>, <tt class="docutils literal"><span class="pre">Float</span></tt>, etc.</dd>
<dt><tt class="docutils literal"><span class="pre">Action</span></tt></dt>
<dd>An action matches the end of a line and is used to execute a callback. It
passes any <tt class="docutils literal"><span class="pre">vars</span></tt> parsed by previous <tt class="docutils literal"><span class="pre">Variable</span></tt> nodes through to the
callback as arguments.</dd>
</dl>
<p>Full details are available in the <a class="reference external" href="http://swapoff.org/cly/docs">API documentation</a>.</p>
</div>
<div class="section" id="node-attributes-and-constructor-arguments">
<h2><a class="toc-backref" href="#id12">Node Attributes and Constructor Arguments</a></h2>
<p>Each node has a set of attributes that define its behaviour, from the regular
expression used to match input, through to the number of times the node can
be traversed in a parse context.</p>
<p>These attributes can be set in four ways:</p>
<p>By passing keyword arguments to the constructor:</p>
<div class="highlight"><pre><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Help&#39;</span><span class="p">,</span> <span class="n">pattern</span><span class="o">=</span><span class="s">r&#39;.+&#39;</span><span class="p">)</span>
</pre></div>
<p>By &quot;calling&quot; the node with keyword arguments:</p>
<div class="highlight"><pre><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Help&#39;</span><span class="p">)(</span><span class="n">pattern</span><span class="o">=</span><span class="s">r&#39;.+&#39;</span><span class="p">)</span>
</pre></div>
<p>With the special <tt class="docutils literal"><span class="pre">Group</span></tt> node. This node will set attributes on <em>all</em>
descendants:</p>
<div class="highlight"><pre><span class="n">Group</span><span class="p">(</span><span class="n">traversals</span><span class="o">=</span><span class="mf">0</span><span class="p">)(</span>
  <span class="n">one</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;One&#39;</span><span class="p">),</span>
  <span class="n">two</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Two&#39;</span><span class="p">),</span>
<span class="p">)</span>
</pre></div>
<p>By subclassing the node and defining the attribute as a class attribute:</p>
<div class="highlight"><pre><span class="k">class</span> <span class="nc">Any</span><span class="p">(</span><span class="n">Node</span><span class="p">):</span>
  <span class="n">pattern</span> <span class="o">=</span> <span class="s">r&#39;.+&#39;</span>
</pre></div>
<p>For details on what attributes are available for each node class, refer to the
<a class="reference external" href="http://swapoff.org/cly/docs">API documentation</a>.</p>
</div>
<div class="section" id="context">
<h2><a class="toc-backref" href="#id13">Context</a></h2>
<p>Each command is parsed within a context. The context stores state information
such as variables collected, number of traversals of nodes, cursor location,
etc. It is most useful when overriding default <tt class="docutils literal"><span class="pre">Node</span></tt> behaviour, where
the <tt class="docutils literal"><span class="pre">vars</span></tt> data member may be inspected for variables that have
already been collected.</p>
</div>
</div>
<div class="section" id="defining-a-grammar-in-xml">
<h1><a class="toc-backref" href="#id14">Defining a Grammar in XML</a></h1>
<p>CLY XML grammars are simply a one-to-one mapping of XML elements to Python
<tt class="docutils literal"><span class="pre">cly.builder.Node</span></tt> objects. Attributes of each element are passed as arguments
to the <tt class="docutils literal"><span class="pre">Node</span></tt> constructor.</p>
<p>Here's a simple example of a grammar defining a single &quot;echo&quot; command:</p>
<div class="highlight"><pre><span class="cp">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="nt">&lt;grammar</span> <span class="na">xmlns=</span><span class="s">&quot;http://swapoff.org/cly/xml&quot;</span><span class="nt">&gt;</span>
  <span class="nt">&lt;node</span> <span class="na">name=</span><span class="s">&quot;echo&quot;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;variable</span> <span class="na">name=</span><span class="s">&quot;text&quot;</span><span class="nt">&gt;</span>
      <span class="nt">&lt;action</span> <span class="na">callback=</span><span class="s">&quot;echo&quot;</span> <span class="na">pattern=</span><span class="s">&quot;.+&quot;</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/variable&gt;</span>
  <span class="nt">&lt;/node&gt;</span>
<span class="nt">&lt;/grammar&gt;</span>
</pre></div>
<div class="section" id="parsing-an-xml-grammar">
<h2><a class="toc-backref" href="#id15">Parsing an XML Grammar</a></h2>
<p>Calling <tt class="docutils literal"><span class="pre">Grammar.from_xml()</span></tt> with an XML string as the first argument will
build a new <tt class="docutils literal"><span class="pre">Grammar</span></tt> object from that XML. An optional second argument
<tt class="docutils literal"><span class="pre">extra_nodes</span></tt> can be used to pass a list of extra <tt class="docutils literal"><span class="pre">Node</span></tt> sub-classes to
recognise as elements. All other keyword arguments will be treated as local
symbols when evaluating attribute values in the XML grammar.</p>
<p>Here's an example that uses the previously defined XML grammar to implement an
&quot;echo&quot; command:</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">cly</span> <span class="kn">import</span> <span class="n">Grammar</span><span class="p">,</span> <span class="n">interact</span>

<span class="k">def</span> <span class="nf">echo</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
    <span class="k">print</span> <span class="n">text</span>

<span class="n">xml_grammar</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;example.xml&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="o">.</span><span class="n">from_xml</span><span class="p">(</span><span class="n">xml_grammar</span><span class="p">,</span> <span class="n">echo</span><span class="o">=</span><span class="n">echo</span><span class="p">)</span>

<span class="n">interact</span><span class="p">(</span><span class="n">grammar</span><span class="p">)</span>
</pre></div>
<p>Here's a slightly more complex example with looping and grouping:</p>
<div class="highlight"><pre><span class="cp">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="nt">&lt;grammar</span> <span class="na">xmlns=</span><span class="s">&quot;http://swapoff.org/cly/xml&quot;</span><span class="nt">&gt;</span>
  <span class="nt">&lt;node</span> <span class="na">name=</span><span class="s">&quot;echo&quot;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;group</span> <span class="na">traversals=</span><span class="s">&quot;0&quot;</span><span class="nt">&gt;</span>
      <span class="nt">&lt;variable</span> <span class="na">name=</span><span class="s">&quot;text&quot;</span><span class="nt">&gt;</span>
        <span class="nt">&lt;alias</span> <span class="na">target=</span><span class="s">&quot;/echo/*&quot;</span><span class="nt">/&gt;</span>
        <span class="nt">&lt;action</span> <span class="na">callback=</span><span class="s">&quot;echo&quot;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;/variable&gt;</span>
    <span class="nt">&lt;/group&gt;</span>
  <span class="nt">&lt;/node&gt;</span>
<span class="nt">&lt;/grammar&gt;</span>
</pre></div>
<p>The Python code is identical.</p>
</div>
<div class="section" id="xml-attribute-type-conversion">
<h2><a class="toc-backref" href="#id16">XML Attribute Type Conversion</a></h2>
<p>All <tt class="docutils literal"><span class="pre">Node</span></tt> constructor arguments that are not strings but are known to the
<tt class="docutils literal"><span class="pre">Parser</span></tt> will be evaluated as Python code, meaning integer arguments will be
converted to integers, callback arguments may contain lambdas, etc.</p>
<p>In this example <tt class="docutils literal"><span class="pre">traversals</span></tt> will be converted to an integer and passed to the
<tt class="docutils literal"><span class="pre">Node</span></tt> constructor:</p>
<div class="highlight"><pre><span class="cp">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="nt">&lt;grammar&gt;</span>
  <span class="nt">&lt;node</span> <span class="na">traversals=</span><span class="s">&quot;0&quot;</span><span class="nt">&gt;</span>
  ...
  <span class="nt">&lt;/node&gt;</span>
<span class="nt">&lt;/grammar&gt;</span>
</pre></div>
<p>This evaluation can also be forced by using the <tt class="docutils literal"><span class="pre">eval</span></tt> XML namespace:</p>
<div class="highlight"><pre><span class="cp">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="nt">&lt;grammar</span> <span class="na">xmlns=</span><span class="s">&quot;http://swapoff.org/cly/xml&quot;</span> <span class="na">xmlns:eval=</span><span class="s">&quot;http://swapoff.org/cly/xml-eval&quot;</span><span class="nt">&gt;</span>
  <span class="nt">&lt;node</span> <span class="na">eval:help=</span><span class="s">&quot;&#39;HELLO WORLD&#39;.title()&quot;</span><span class="nt">/&gt;</span>
    ...
  <span class="nt">&lt;/node&gt;</span>
<span class="nt">&lt;/grammar&gt;</span>
</pre></div>
</div>
</div>
<div class="section" id="parsing">
<h1><a class="toc-backref" href="#id17">Parsing</a></h1>
<p>A grammar is simply a data structure. To actually utilise it one needs to bind
it to a <tt class="docutils literal"><span class="pre">Parser</span></tt> object and parse some input with it. The parser takes care
of creating a <tt class="docutils literal"><span class="pre">Context</span></tt> for each parse run, parsing the input, and executing
any callbacks.</p>
<div class="section" id="parse-context">
<h2><a class="toc-backref" href="#id18">Parse Context</a></h2>
<p>A parse context is created automatically when input is parsed. It contains all
the information needed to parse input tokens, including the current cursor
position in the input stream, the current node in the grammar, variables
collected and a history of nodes traversed.</p>
<p>Basic usage is:</p>
<div class="highlight"><pre><span class="n">parser</span> <span class="o">=</span> <span class="n">Parser</span><span class="p">(</span><span class="n">grammar</span><span class="p">)</span>
<span class="n">context</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s">&#39;some input text&#39;</span><span class="p">)</span>
<span class="k">print</span> <span class="n">context</span><span class="o">.</span><span class="n">vars</span>
</pre></div>
<p>If the input is invalid the context will have consumed as much input as
possible. The attributes <tt class="docutils literal"><span class="pre">parsed</span></tt> and <tt class="docutils literal"><span class="pre">remaining</span></tt> contain how much text has
been consumed and remains, respectively. The context has a number of additional
attributes and methods that are useful to both <tt class="docutils literal"><span class="pre">Node</span></tt> implementations and
<tt class="docutils literal"><span class="pre">Parser</span></tt> users. These are documented in detail in the API documentation.</p>
</div>
<div class="section" id="passing-user-defined-objects-to-callbacks">
<h2><a class="toc-backref" href="#id19">Passing User-defined Objects to Callbacks</a></h2>
<p>Sometimes it's useful to be able to pass an arbitrary object through to
the grammar callbacks. This is achieved by first enabling this behaviour
on the desired action nodes by either passing <tt class="docutils literal"><span class="pre">with_user_context=True</span></tt>
to the constructor or enabled across the entire grammar by doing the
same on the <tt class="docutils literal"><span class="pre">Parser</span></tt> constructor. Once enabled, simply pass the object
to the <tt class="docutils literal"><span class="pre">execute()</span></tt> method via the <tt class="docutils literal"><span class="pre">user_context</span></tt> parameter. That
object will then be provided to all action callbacks as the first
parameter.</p>
<p>One way of applying this is by binding all callbacks to methods on a
single <em>class</em>, then passing an instance of that class as the context:</p>
<div class="highlight"><pre><span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>

  <span class="k">def</span> <span class="nf">one</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">one</span><span class="p">):</span>
    <span class="k">print</span> <span class="s">&quot;One:&quot;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">one</span>

  <span class="k">def</span> <span class="nf">two</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">two</span><span class="p">):</span>
    <span class="k">print</span> <span class="s">&quot;Two:&quot;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">two</span>

<span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
  <span class="n">one</span><span class="o">=</span><span class="n">Variable</span><span class="p">(</span><span class="s">&#39;One&#39;</span><span class="p">)(</span>
    <span class="n">Action</span><span class="p">(</span><span class="s">&#39;Execute one&#39;</span><span class="p">,</span> <span class="n">A</span><span class="o">.</span><span class="n">one</span><span class="p">),</span>
    <span class="p">),</span>
  <span class="n">two</span><span class="o">=</span><span class="n">Variable</span><span class="p">(</span><span class="s">&#39;Two&#39;</span><span class="p">)(</span>
    <span class="n">Action</span><span class="p">(</span><span class="s">&#39;Execute two&#39;</span><span class="p">,</span> <span class="n">A</span><span class="o">.</span><span class="n">two</span><span class="p">),</span>
    <span class="p">),</span>
<span class="p">)</span>

<span class="n">a</span> <span class="o">=</span> <span class="n">A</span><span class="p">(</span><span class="s">&#39;a&#39;</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">A</span><span class="p">(</span><span class="s">&#39;b&#39;</span><span class="p">)</span>

<span class="n">parser</span> <span class="o">=</span> <span class="n">Parser</span><span class="p">(</span><span class="n">grammar</span><span class="p">,</span> <span class="n">with_user_context</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

<span class="n">parser</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&#39;one&#39;</span><span class="p">,</span> <span class="n">user_context</span><span class="o">=</span><span class="n">a</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&#39;two&#39;</span><span class="p">,</span> <span class="n">user_context</span><span class="o">=</span><span class="n">b</span><span class="p">)</span>
</pre></div>
<p>This will output:</p>
<pre class="literal-block">
One: a one
One: b two
</pre>
</div>
</div>
</div>
</body>
</html>