2020-05-13 01:33:17 +03:00
<!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" >
2020-05-14 23:55:05 +03:00
< link href = "../docs-assets/Preform-Colours.css" rel = "stylesheet" rev = "stylesheet" type = "text/css" >
2020-05-13 01:33:17 +03:00
< / 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 >
2020-08-27 17:50:24 +03:00
< li > < a href = "../assertions-module/index.html" > assertions< / a > < / li >
< li > < a href = "../values-module/index.html" > values< / a > < / li >
< li > < a href = "../knowledge-module/index.html" > knowledge< / a > < / li >
< li > < a href = "../imperative-module/index.html" > imperative< / a > < / li >
< li > < a href = "../runtime-module/index.html" > runtime< / a > < / li >
2020-05-13 01:33:17 +03:00
< 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 >
2020-05-20 02:02:28 +03:00
< / ul > < h2 > Services< / h2 > < ul >
2020-05-13 01:33:17 +03:00
< li > < a href = "../arch-module/index.html" > arch< / a > < / li >
2020-08-27 17:50:24 +03:00
< li > < a href = "../calculus-module/index.html" > calculus< / a > < / li >
2020-05-13 01:33:17 +03:00
< li > < a href = "../html-module/index.html" > html< / a > < / li >
2020-05-20 02:02:28 +03:00
< li > < a href = "../inflections-module/index.html" > inflections< / a > < / li >
2020-08-27 17:50:24 +03:00
< li > < a href = "../kinds-module/index.html" > kinds< / a > < / li >
2020-05-20 02:02:28 +03:00
< li > < a href = "../linguistics-module/index.html" > linguistics< / a > < / li >
< li > < a href = "../problems-module/index.html" > problems< / a > < / li >
2020-08-27 17:50:24 +03:00
< li > < a href = "../syntax-module/index.html" > syntax< / a > < / li >
< li > < a href = "index.html" > < span class = "selectedlink" > words< / span > < / a > < / li >
2020-05-13 01:33:17 +03:00
< 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" >
2020-05-20 13:36:42 +03:00
< 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 >
2020-05-13 01:33:17 +03:00
< p class = "purpose" > A brief guide to Preform and how to use it.< / p >
2020-08-27 17:50:24 +03:00
< p class = "commentary firstcommentary" > < a id = "SP1" class = "paragraph-anchor" > < / a > < b > § 1. < / b > Preform is a meta-language for writing a simple grammar: it's in some sense
2020-05-14 23:55:05 +03:00
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,
2020-05-13 01:33:17 +03:00
< / p >
2020-05-14 23:55:05 +03:00
< 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:
2020-05-13 01:33:17 +03:00
< / p >
< pre class = "displayed-code all-displayed-code code-font" >
2020-05-14 23:55:05 +03:00
< 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
2020-05-17 13:51:27 +03:00
by the Inform compiler modules; all of the rest are called "regular" and are
defined rather like < competitor> , i.e., with grammar spelled out.
2020-05-14 23:55:05 +03:00
< / p >
2020-08-27 17:50:24 +03:00
< p class = "commentary firstcommentary" > < a id = "SP2" class = "paragraph-anchor" > < / a > < b > § 2. < / b > Preform grammar is stored in a text file which is read by Inform early in
2020-05-17 02:20:21 +03:00
its run: see < a href = "4-lp.html#SP1" class = "internal" > LoadPreform::load< / a > . In principle, different natural language
2020-05-14 23:55:05 +03:00
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
2020-05-17 13:51:27 +03:00
it can fully advance. Still, the principle is that the user can therefore
2020-05-14 23:55:05 +03:00
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 >
2020-07-28 21:19:38 +03:00
< 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 >
2020-05-13 01:33:17 +03:00
< / pre >
2020-05-14 23:55:05 +03:00
< 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
2020-05-17 13:51:27 +03:00
right-hand side, which is essentially C, becomes code which takes action
on any successful match against the grammar.
2020-05-14 23:55:05 +03:00
< / p >
2020-08-27 17:50:24 +03:00
< p class = "commentary firstcommentary" > < a id = "SP3" class = "paragraph-anchor" > < / a > < b > § 3. < / b > Each nonterminal, when successfully matched, can provide both or more usually
2020-05-14 23:55:05 +03:00
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 > .
2020-05-13 01:33:17 +03:00
< / p >
< p class = "commentary" > Usually, though, the result(s) of a nonterminal depend on the result(s) of
2020-05-14 23:55:05 +03:00
other nonterminals used to make the match. If that's so, then the expression
2020-05-17 13:51:27 +03:00
right of the arrow will have to combine these. In such a compositing expression,
2020-05-13 01:33:17 +03:00
so called because it composes together the various intermediate results into
2020-05-14 23:55:05 +03:00
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
2020-05-17 13:51:27 +03:00
pointer results. For example, you could make a very crude calculator with:
2020-05-14 23:55:05 +03:00
< / p >
2020-05-17 13:51:27 +03:00
< 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 >
2020-07-28 21:19:38 +03:00
< 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" > { pass 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 >
2020-05-17 13:51:27 +03:00
< / 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> :
2020-05-14 23:55:05 +03:00
< / 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 >
2020-07-28 21:19:38 +03:00
< 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" > { pass 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" > { pass 1 }< / span >
2020-05-14 23:55:05 +03:00
< / 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,
2020-05-13 01:33:17 +03:00
"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
2020-07-28 21:19:38 +03:00
of, so < span class = "extract" > < span class = "Preform-extract-syntax" > pass< / span > < / span > can't be used.
2020-05-13 01:33:17 +03:00
< / p >
2020-08-27 17:50:24 +03:00
< p class = "commentary firstcommentary" > < a id = "SP4" class = "paragraph-anchor" > < / a > < b > § 4. < / b > The arrows and expressions are optional, and if they are omitted, then the
2020-05-14 23:55:05 +03:00
result integer is set to the alternative number, counting up from 0. For
2020-05-13 01:33:17 +03:00
example, given the following, "polkadot" matches with result 1, and "green"
with result 2.
< / p >
2020-05-14 23:55:05 +03:00
< 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 >
2020-05-13 01:33:17 +03:00
< / pre >
2020-08-27 17:50:24 +03:00
< p class = "commentary firstcommentary" > < a id = "SP5" class = "paragraph-anchor" > < / a > < b > § 5. < / b > As a convenient abbreviation, a slash character can be used to divide
2020-05-17 13:51:27 +03:00
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 >
2020-07-28 21:19:38 +03:00
< 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 >
2020-05-17 13:51:27 +03:00
< / 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 >
2020-08-27 17:50:24 +03:00
< p class = "commentary firstcommentary" > < a id = "SP6" class = "paragraph-anchor" > < / a > < b > § 6. < / b > So far, the only ingredients of Preform syntax have been nonterminals and
2020-05-17 02:20:21 +03:00
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 >
2020-05-17 13:51:27 +03:00
< 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 >
2020-08-27 17:50:24 +03:00
< p class = "commentary firstcommentary" > < a id = "SP7" class = "paragraph-anchor" > < / a > < b > § 7. < / b > The alternative lines (or "productions", as they're called) in a regular
2020-05-17 13:51:27 +03:00
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 >
2020-07-28 21:19:38 +03:00
< 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" > { pass 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" > { pass 1 }< / span >
2020-05-17 13:51:27 +03:00
< / 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 >
2020-07-28 21:19:38 +03:00
< 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 >
2020-05-17 13:51:27 +03:00
< / 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 >
2020-07-28 21:19:38 +03:00
< 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 >
2020-05-17 13:51:27 +03:00
< / 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 >
2020-07-28 21:19:38 +03:00
< 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 >
2020-05-17 13:51:27 +03:00
< / 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 >
2020-08-27 17:50:24 +03:00
< p class = "commentary firstcommentary" > < a id = "SP8" class = "paragraph-anchor" > < / a > < b > § 8. < / b > A similar form if remapping is allowed with word ranges, using a special
2020-05-17 13:51:27 +03:00
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 >
2020-08-27 17:50:24 +03:00
< p class = "commentary firstcommentary" > < a id = "SP9" class = "paragraph-anchor" > < / a > < b > § 9. < / b > Preform turns out to be a useful notation for patterns of wording, and can
2020-05-22 11:38:17 +03:00
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:
2020-05-19 18:36:50 +03:00
< / p >
2020-05-22 11:38:17 +03:00
< 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 > .
2020-05-19 18:36:50 +03:00
< / li > < / ul >
2020-08-27 17:50:24 +03:00
< p class = "commentary firstcommentary" > < a id = "SP10" class = "paragraph-anchor" > < / a > < b > § 10. < / b > Finally, syntax errors in Preform are reported by < a href = "4-pu.html#SP8" class = "internal" > PreformUtilities::production_error< / a > .
2020-05-19 18:36:50 +03:00
< / p >
2020-05-13 01:33:17 +03:00
< nav role = "progress" > < div class = "progresscontainer" >
2020-05-22 11:38:17 +03:00
< 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 >
2020-05-13 01:33:17 +03:00
< / nav > <!-- End of weave -->
< / main >
< / body >
< / html >