mirror of
https://github.com/ganelson/inform.git
synced 2024-07-16 22:14:23 +03:00
419 lines
40 KiB
HTML
419 lines
40 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>About Preform</title>
|
|
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<meta name="viewport" content="width=device-width initial-scale=1">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
|
|
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Preform-Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
|
|
</head>
|
|
<body class="commentary-font">
|
|
<nav role="navigation">
|
|
<h1><a href="../index.html">
|
|
<img src="../docs-assets/Inform.png" height=72">
|
|
</a></h1>
|
|
<ul><li><a href="../compiler.html">compiler tools</a></li>
|
|
<li><a href="../other.html">other tools</a></li>
|
|
<li><a href="../extensions.html">extensions and kits</a></li>
|
|
<li><a href="../units.html">unit test tools</a></li>
|
|
</ul><h2>Compiler Webs</h2><ul>
|
|
<li><a href="../inbuild/index.html">inbuild</a></li>
|
|
<li><a href="../inform7/index.html">inform7</a></li>
|
|
<li><a href="../inter/index.html">inter</a></li>
|
|
</ul><h2>Inbuild Modules</h2><ul>
|
|
<li><a href="../supervisor-module/index.html">supervisor</a></li>
|
|
</ul><h2>Inform7 Modules</h2><ul>
|
|
<li><a href="../core-module/index.html">core</a></li>
|
|
<li><a href="../kinds-module/index.html">kinds</a></li>
|
|
<li><a href="../if-module/index.html">if</a></li>
|
|
<li><a href="../multimedia-module/index.html">multimedia</a></li>
|
|
<li><a href="../index-module/index.html">index</a></li>
|
|
</ul><h2>Inter Modules</h2><ul>
|
|
<li><a href="../bytecode-module/index.html">bytecode</a></li>
|
|
<li><a href="../building-module/index.html">building</a></li>
|
|
<li><a href="../codegen-module/index.html">codegen</a></li>
|
|
</ul><h2>Services</h2><ul>
|
|
<li><a href="../arch-module/index.html">arch</a></li>
|
|
<li><a href="../syntax-module/index.html">syntax</a></li>
|
|
<li><a href="index.html"><span class="selectedlink">words</span></a></li>
|
|
<li><a href="../html-module/index.html">html</a></li>
|
|
<li><a href="../inflections-module/index.html">inflections</a></li>
|
|
<li><a href="../linguistics-module/index.html">linguistics</a></li>
|
|
<li><a href="../problems-module/index.html">problems</a></li>
|
|
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
|
|
|
|
</ul>
|
|
</nav>
|
|
<main role="main">
|
|
<!--Weave of 'About Preform' generated by Inweb-->
|
|
<div class="breadcrumbs">
|
|
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../compiler.html">Services</a></li><li><a href="index.html">words</a></li><li><a href="index.html#4">Chapter 4: Parsing</a></li><li><b>About Preform</b></li></ul></div>
|
|
<p class="purpose">A brief guide to Preform and how to use it.</p>
|
|
|
|
<p class="commentary firstcommentary"><a id="SP1"></a><b>§1. </b>Preform is a meta-language for writing a simple grammar: it's in some sense
|
|
pre-Inform, because it defines the Inform language itself, and has to be read
|
|
by the <a href="index.html" class="internal">words</a> module (on behalf of Inform) before Inform can parse anything.
|
|
For example,
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><competitor></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><ordinal-number></span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">runner</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">runner</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">no</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><cardinal-number></span>
|
|
</pre>
|
|
<p class="commentary">The <span class="extract"><span class="Preform-extract-syntax">::=</span></span> indicates a definition: the following-on lines, divided by the
|
|
vertical stroke, are possibilities tried in turn. Each "non-terminal", written
|
|
in angle brackets, can in principle match (or not match) against any wording.
|
|
When writing code in InC (the slight extension of C granted by inweb: see
|
|
<a href="../../../inweb/docs/M-tid.html" class="internal">The InC Dialect (in inweb)</a>), this can actually be written as a function call:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (<</span><span class="identifier-syntax">competitor</span><span class="plain-syntax">>(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) ...</span>
|
|
</pre>
|
|
<p class="commentary">This function returns <span class="extract"><span class="extract-syntax">TRUE</span></span> if a match is made, and <span class="extract"><span class="extract-syntax">FALSE</span></span> if it is not.
|
|
But if a match is indeed made, there are side-effects too, as we shall see.
|
|
</p>
|
|
|
|
<p class="commentary">So, for example, the above grammar would match any of these possibilities:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> 7th runner</span>
|
|
<span class="plain-syntax"> third runner</span>
|
|
<span class="plain-syntax"> runner no 7</span>
|
|
<span class="plain-syntax"> runner no three</span>
|
|
</pre>
|
|
<p class="commentary">but would fail, for example,
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax"> runner</span>
|
|
<span class="plain-syntax"> 7 runner</span>
|
|
<span class="plain-syntax"> runner no 7th</span>
|
|
<span class="plain-syntax"> ice cream sandwich</span>
|
|
</pre>
|
|
<p class="commentary">A small number of nonterminals are "internal", meaning that they are defined
|
|
by the Inform compiler modules; all of the rest are called "regular" and are
|
|
defined rather like <competitor>, i.e., with grammar spelled out.
|
|
</p>
|
|
|
|
<p class="commentary firstcommentary"><a id="SP2"></a><b>§2. </b>Preform grammar is stored in a text file which is read by Inform early in
|
|
its run: see <a href="4-lp.html#SP1" class="internal">LoadPreform::load</a>. In principle, different natural language
|
|
definitions can be made: thus, French translators could supply a French-localised
|
|
Preform grammar. In practice this whole area of Inform needs more work before
|
|
it can fully advance. Still, the principle is that the user can therefore
|
|
modify the underlying grammar used by Inform.
|
|
</p>
|
|
|
|
<p class="commentary">The standard Inform distribution comes with the English Preform: in fact, the
|
|
file is in <span class="extract"><span class="extract-syntax">inform7/Internal/Languages/English/Syntax.preform</span></span>. However,
|
|
this file is not the "original": it is mechanically generated from the source
|
|
code of Inform by <a href="../../../inweb/docs/index.html" class="internal">inweb</a>. For example, the excerpt of grammar might have
|
|
come from some (hypothetical) source code looking like this:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><competitor></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><ordinal-number></span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">runner</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> TRUE</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">runner</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">no</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><cardinal-number></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> FALSE</span>
|
|
</pre>
|
|
<p class="commentary">Definitions like this one are scattered all across the Inform web, in order
|
|
to keep them close to the code which relates to them. <a href="../../../inweb/docs/index.html" class="internal">inweb</a> tears this
|
|
code in half lengthways: the left-hand side goes into the <span class="extract"><span class="Preform-extract-syntax">Syntax.preform</span></span>
|
|
file mentioned above, and is then read into Inform at run-time; and the
|
|
right-hand side, which is essentially C, becomes code which takes action
|
|
on any successful match against the grammar.
|
|
</p>
|
|
|
|
<p class="commentary firstcommentary"><a id="SP3"></a><b>§3. </b>Each nonterminal, when successfully matched, can provide both or more usually
|
|
just one of two results: an integer, to be stored in a variable called <span class="extract"><span class="Preform-extract-syntax">*X</span></span>,
|
|
and a void pointer, to be stored in <span class="extract"><span class="Preform-extract-syntax">*XP</span></span>, which is usually an object.
|
|
</p>
|
|
|
|
<p class="commentary">The example above, <span class="extract"><span class="Preform-extract-syntax"><competitor></span></span>, only results in an integer. The <span class="extract"><span class="Preform-extract-syntax">==></span></span> arrow
|
|
is optional, but if present, it says what the integer result is if the given
|
|
production is matched. So, for example, "runner bean" or "beetroot" would not
|
|
match <competitor>; "4th runner" would match with integer result <span class="extract"><span class="Preform-extract-syntax">TRUE</span></span>;
|
|
"runner no 17" would match with integer result <span class="extract"><span class="Preform-extract-syntax">FALSE</span></span>.
|
|
</p>
|
|
|
|
<p class="commentary">Usually, though, the result(s) of a nonterminal depend on the result(s) of
|
|
other nonterminals used to make the match. If that's so, then the expression
|
|
right of the arrow will have to combine these. In such a compositing expression,
|
|
so called because it composes together the various intermediate results into
|
|
one final result, <span class="extract"><span class="Preform-extract-syntax">R[1]</span></span> is the integer result of the first nonterminal in
|
|
the production, <span class="extract"><span class="Preform-extract-syntax">R[2]</span></span> the second, and so on; <span class="extract"><span class="Preform-extract-syntax">RP[1]</span></span> and so on hold the
|
|
pointer results. For example, you could make a very crude calculator with:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><arithmetic></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><cardinal-number></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> R[1]</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><cardinal-number></span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">plus</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><cardinal-number></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> R[1]+R[2]</span>
|
|
</pre>
|
|
<p class="commentary">Here <span class="extract"><span class="Preform-extract-syntax">R[1]+R[2]</span></span> produces a result by composition of the two results of
|
|
the <cardinal-number> nontermimal which occurred when parsing the line.
|
|
So, for example, "seven" matches <arithmetic> with result 7, and "two plus
|
|
three" with result 5.
|
|
</p>
|
|
|
|
<p class="commentary">Or consider the following refinement of <competitor>:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><competitor></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">the</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">pacemaker</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 1</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><ordinal-number></span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">runner</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> R[1]</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">runner</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">no</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><cardinal-number></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> R[1]</span>
|
|
</pre>
|
|
<p class="commentary">Now "4th runner" matches with integer result 4, because <ordinal-number>
|
|
matches "4th" with integer result 4, and that goes into <span class="extract"><span class="Preform-extract-syntax">R[1]</span></span>. Similarly,
|
|
"runner no 17" ends up with integer result 17. "The pacemaker" matches
|
|
with integer result 1; here there are no intermediate results to make use
|
|
of, so <span class="extract"><span class="Preform-extract-syntax">R[...]</span></span> can't be used.
|
|
</p>
|
|
|
|
<p class="commentary firstcommentary"><a id="SP4"></a><b>§4. </b>The arrows and expressions are optional, and if they are omitted, then the
|
|
result integer is set to the alternative number, counting up from 0. For
|
|
example, given the following, "polkadot" matches with result 1, and "green"
|
|
with result 2.
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><race-jersey></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">yellow</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">polkadot</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">green</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">white</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP5"></a><b>§5. </b>As a convenient abbreviation, a slash character can be used to divide
|
|
alternative possibilities for a single word. For example:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><race-jersey></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">yellow</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">polkadot/polka-dot</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">green</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">white</span>
|
|
</pre>
|
|
<p class="commentary">matches "polka-dot" equivalently to "polkadot".
|
|
</p>
|
|
|
|
<p class="commentary">Another convenient notation is the caret <span class="extract"><span class="Preform-extract-syntax">^</span></span>, which negates the effect of
|
|
a token. For example,
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><competitor></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">the</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">^adjudicator</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 1</span>
|
|
</pre>
|
|
<p class="commentary">matches "the pacemaker", "the cyclist", etc. — the anything at all, but not
|
|
"the adjudicator".
|
|
</p>
|
|
|
|
<p class="commentary">The final modifying notation is the underscore <span class="extract"><span class="Preform-extract-syntax">_</span></span>, which forbids unexpected
|
|
use of upper casing. Thus
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><race-jersey></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">yellow</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">polkadot</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">_green</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">white</span>
|
|
</pre>
|
|
<p class="commentary">means that it will match Yellow, yellow, Polkadot, polkadot, green, White
|
|
and white, but not Green (except as the first word of a sentence, where
|
|
the use of capitalisation has no significance).
|
|
</p>
|
|
|
|
<p class="commentary">If the modifiers <span class="extract"><span class="Preform-extract-syntax">^</span></span> or <span class="extract"><span class="Preform-extract-syntax">_</span></span> are given for the first of a series of slashed
|
|
alternatives, they apply to all of the alternatives: thus <span class="extract"><span class="Preform-extract-syntax">^cat/dog</span></span> matches
|
|
any word which is neither "cat" nor "dog".
|
|
</p>
|
|
|
|
<p class="commentary">If these characters are needed in their literal form, a backslash <span class="extract"><span class="Preform-extract-syntax">\</span></span> can
|
|
be used to escape them. Thus <span class="extract"><span class="Preform-extract-syntax">\_green</span></span> actually matches <span class="extract"><span class="Preform-extract-syntax">_green</span></span>.
|
|
</p>
|
|
|
|
<p class="commentary firstcommentary"><a id="SP6"></a><b>§6. </b>So far, the only ingredients of Preform syntax have been nonterminals and
|
|
fixed words, but Preform also has "wildcards". For example, in
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><competitor></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">man</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">with</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">on</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">his</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span>
|
|
</pre>
|
|
<p class="commentary">would match, for example, "man with number 17 on his back", or "man with a
|
|
chip on his shoulder". <span class="extract"><span class="Preform-extract-syntax">...</span></span> matches any non-empty wording, and the text
|
|
actually matched is recorded for any successful match. Wordings like this
|
|
are numbered upwards from 1 to a maximum of 4, and are usually retrieved by
|
|
whatever part of Inform requested the parse, using the <span class="extract"><span class="Preform-extract-syntax">GET_RW</span></span> macro. For
|
|
example:
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">TEXT GET_RW(<competitor>, 1) GET_RW(<competitor>, 2)</span>
|
|
<span class="plain-syntax">man with number 17 on his back number 17 back</span>
|
|
<span class="plain-syntax">man with a chip on his shoulder a chip shoulder</span>
|
|
</pre>
|
|
<p class="commentary">A few internal nonterminals also generate word ranges, using <span class="extract"><span class="extract-syntax">PUT_RW</span></span> to do so,
|
|
and word ranges can also be inherited up from one nonterminal to another with
|
|
<span class="extract"><span class="extract-syntax">INHERIT_RANGES</span></span>: see <a href="4-lp.html" class="internal">Loading Preform</a> for definitions of these macros.
|
|
</p>
|
|
|
|
<p class="commentary">There are in fact several different wildcards:
|
|
</p>
|
|
|
|
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">...</span></span> matches any non-empty text, as shown above.
|
|
</li><li>(b) <span class="extract"><span class="extract-syntax">***</span></span> matches any text, including possibly the empty text.
|
|
</li><li>(c) <span class="extract"><span class="extract-syntax">......</span></span> matches any non-empty text in which brackets are used in a
|
|
balanced way — thus they would match "alpha beta gamma" or "alpha (the
|
|
Greek letter)", but not "alpha (the" or "Greek letter)".
|
|
</li><li>(d) <span class="extract"><span class="extract-syntax">###</span></span> matches any single word, counting words as the lexer does.
|
|
</li></ul>
|
|
<p class="commentary">It is also possible to use braces to widen ranges. For example,
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><competitor></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">man</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">with</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">on</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">his</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">...}</span>
|
|
</pre>
|
|
<p class="commentary">groups together anything matching <span class="extract"><span class="Preform-extract-syntax">... on his ...</span></span> into a single range. There
|
|
need not even be a wildcard inside the braces:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><competitor></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{man}</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">with</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">on</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">his</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">...}</span>
|
|
</pre>
|
|
<p class="commentary">works fine, and makes two ranges, the first of which is always just "man".
|
|
</p>
|
|
|
|
<p class="commentary">Once again, literal brace characters can be achieved using the <span class="extract"><span class="Preform-extract-syntax">\</span></span> escape.
|
|
</p>
|
|
|
|
<p class="commentary firstcommentary"><a id="SP7"></a><b>§7. </b>The alternative lines (or "productions", as they're called) in a regular
|
|
definition are normally given the internal numbers 0, 1, 2, 3... in the
|
|
order in which they appear. For example, in
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><competitor></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">the</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">pacemaker</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 1</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><ordinal-number></span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">runner</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> R[1]</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">runner</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">no</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><cardinal-number></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> R[1]</span>
|
|
</pre>
|
|
<p class="commentary">the <span class="extract"><span class="Preform-extract-syntax">the pacemaker</span></span> row is numbered 0, <span class="extract"><span class="Preform-extract-syntax"><ordinal-number> runner</span></span> is numbered 1,
|
|
and so on. Those "match numbers" have little outward significance, but help
|
|
to determine the result when a successful match is made. Consider:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><letter-score></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">alpha</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 10</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">beta</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 20</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">gamma</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 30</span>
|
|
</pre>
|
|
<p class="commentary">Here, matching against "beta" produces 20 — the result on the same row. But
|
|
we can mess with that:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><letter-score></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">/c/</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">alpha</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 10</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">/a/</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">beta</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 20</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">/b/</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">gamma</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 30</span>
|
|
</pre>
|
|
<p class="commentary">The special notation <span class="extract"><span class="Preform-extract-syntax">/X/</span></span>, where <span class="extract"><span class="Preform-extract-syntax">X</span></span> is a lower-case letter, marks the row
|
|
as having a different number from the obvious one. <span class="extract"><span class="Preform-extract-syntax">/a/</span></span> means 0, <span class="extract"><span class="Preform-extract-syntax">/b/</span></span> means
|
|
1, and so on. The practical effect of the above is to achieve the equivalent
|
|
of this:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><letter-score></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">beta</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 10</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">gamma</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 20</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">alpha</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></span><span class="Preform-plain-syntax"> 30</span>
|
|
</pre>
|
|
<p class="commentary">That might seem a stupidly obfuscatory thing to do, and indeed it is, when
|
|
done in the main Inform source code — which is why we never do it. But
|
|
Preform can also be used by translators of Inform to other languages, who might
|
|
supply, e.g., a French version of <span class="extract"><span class="Preform-extract-syntax">Syntax.preform</span></span>. Or suppose in this instance
|
|
that the Inform source code contains <letter-score> but that a translator into
|
|
Hebrew wants to override that definition. Her Hebrew version of <span class="extract"><span class="Preform-extract-syntax">Syntax.preform</span></span>
|
|
could then write:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><letter-score></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">/a/</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">aleph</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">/a/</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">alef</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">/b/</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">beth</span>
|
|
</pre>
|
|
<p class="commentary">This translator wanted to provide two alternative ways to write the Hebrew
|
|
version of "alpha", one for "beta", but none for "gamma". Using the remappings
|
|
<span class="extract"><span class="Preform-extract-syntax">/a/</span></span> and <span class="extract"><span class="Preform-extract-syntax">/b/</span></span> here, she is able to make her lines behave as if they were
|
|
lines 1, 1, 2 of the original, rather than 1, 2, 3, which would have been the
|
|
default.
|
|
</p>
|
|
|
|
<p class="commentary">Because there are a few rather long nonterminal definitions in Inform, the
|
|
labelling runs <span class="extract"><span class="Preform-extract-syntax">/a/</span></span>, <span class="extract"><span class="Preform-extract-syntax">/b/</span></span>, ..., <span class="extract"><span class="Preform-extract-syntax">/z/</span></span> and then continues <span class="extract"><span class="Preform-extract-syntax">/aa/</span></span>, <span class="extract"><span class="Preform-extract-syntax">/bb/</span></span>,
|
|
..., <span class="extract"><span class="Preform-extract-syntax">/zz/</span></span>, thus allowing for up to 52 productions to be remapped in this way.
|
|
</p>
|
|
|
|
<p class="commentary firstcommentary"><a id="SP8"></a><b>§8. </b>A similar form if remapping is allowed with word ranges, using a special
|
|
notation. Suppose the Inform source contained:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><coloured-thing></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><race-colour></span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">}</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">jersey/helmet</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary">but we want this in French, where adjectives usually come after nouns. So this:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><coloured-thing></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">maillot/casque</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">}</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><race-colour></span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">}</span>
|
|
</pre>
|
|
<p class="commentary">wouldn't work — it would set the word ranges the wrong way around. Instead:
|
|
</p>
|
|
|
|
<pre class="Preform-displayed-code all-displayed-code code-font">
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><coloured-thing></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
|
|
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">maillot/casque</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">}?2</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><race-colour></span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">}?1</span>
|
|
</pre>
|
|
<p class="commentary">says that word range 2 is to be the article of clothing, and word range 1 the
|
|
colour.
|
|
</p>
|
|
|
|
<p class="commentary firstcommentary"><a id="SP9"></a><b>§9. </b>Preform turns out to be a useful notation for patterns of wording, and can
|
|
be put to other uses besides parsing source text. For these other uses, see
|
|
<a href="4-pu.html" class="internal">Preform Utilities</a>. Specifically, and in rough order of complexity:
|
|
</p>
|
|
|
|
<ul class="items"><li>● Specifying text being generated by Inform — see <a href="4-pu.html#SP1" class="internal">PreformUtilities::merge</a>.
|
|
</li><li>● Specifying replacements of one set of words by another — see
|
|
<a href="4-pu.html#SP4" class="internal">PreformUtilities::find_corresponding_word</a>.
|
|
</li><li>● Specifying miscellaneous entries for the lexicon in the Inform index — see
|
|
<a href="4-pu.html#SP5" class="internal">PreformUtilities::enter_lexicon</a>.
|
|
</li><li>● Saying how to build a trie which will detect patterns in a single word and
|
|
then modify it — see <a href="4-pu.html#SP6" class="internal">PreformUtilities::define_trie</a>.
|
|
</li></ul>
|
|
<p class="commentary firstcommentary"><a id="SP10"></a><b>§10. </b>Finally, syntax errors in Preform are reported by <a href="4-pu.html#SP8" class="internal">PreformUtilities::production_error</a>.
|
|
</p>
|
|
|
|
<nav role="progress"><div class="progresscontainer">
|
|
<ul class="progressbar"><li class="progressprev"><a href="3-idn.html">❮</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresscurrent">ap</li><li class="progresssection"><a href="4-nnt.html">nnt</a></li><li class="progresssection"><a href="4-lp.html">lp</a></li><li class="progresssection"><a href="4-to.html">to</a></li><li class="progresssection"><a href="4-le.html">le</a></li><li class="progresssection"><a href="4-ni.html">ni</a></li><li class="progresssection"><a href="4-prf.html">prf</a></li><li class="progresssection"><a href="4-bn.html">bn</a></li><li class="progresssection"><a href="4-ins.html">ins</a></li><li class="progresssection"><a href="4-pu.html">pu</a></li><li class="progressnext"><a href="4-nnt.html">❯</a></li></ul></div>
|
|
</nav><!--End of weave-->
|
|
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|