Introduction

Here is a grammar-driven peal proving program, available for download for free. This document describes how to write composition specifications for it, so that you can search for touches, quarter-peals or even peals. If you already have a composition, you can write an explicit specification for that composition and this program will prove it for you. It will even summarise any music the composition contains.

The simple ringing language as used in MicroSiril and other peal provers has been in use for many years. It gives an ‘identifier = expansion’ based syntax that expands to raw place notation for input to a peal prover program. Thus the prover need have no concept of method structure, or of the concept of leads, blocks, and calls. This is an ideal ringing language for proving a fixed composition, though it doesn’t lend itself readily to back-tracking composition searches. In particular it cannot be used to specify a constrained back-tracking search. For example, if we wanted to search for peals based on certain fixed block patterns with optional calling positions or choices of spliced method, we could not specify the layout of the fixed parts of the touch in a way that would allow a back-tracking program to perform this constrained search.

The elementary ringing language described here is based on the concepts of MicroSiril, and adds new constructs that allow options for changes or leads within a touch. It enables a basic round block to be used, and options for variations to that block to be exercised. It allows two kinds of block repetition: one that repeats the optional leads using backtracking, and one where a repeated block must reuse the leads as set the previous time the block was used in the proof. In short, ERIL provides features a composition searcher might use when parts of a composition are designed, but searches need to be made to join known blocks together, or to get the desired length.

The program ​eril.exe is a program that reads an ERIL touch specification from a file, then proves the set of all touches that match that specification. As usual with all freeware, no warranties are given for its performance, though I have not yet had a false proof come out of it! The program is used in the following way.

  • First, prepare your touch description file using a text editor of your choice, like notepad or notepad++. The ERIL grammar rules are described lower in this article.
  • Launch a command prompt window, and navigate to the folder where your touch description file lives.
  • Run the eril.exe program: eril touchDescriptionFilePath outputTouchFilePath
  • Use a text editor again to inspect the list of true touches in the output touch file that match the ERIL touch specification.

Example

Let's assume you unzipped your eril.zip file into a folder C:\MyErilFiles, and you created your ERIL composition description file in a folder C:\MyTouches with the name coolstedmanscript.txt.

Launch a command prompt window, then at the command prompt type the command CD C:\MyTouches followed by the return key.

To run eril, type the command C:\MyErilFiles\eril.exe coolstedmanscript.txt foundtouches.txt followed by the return key.

If you've used a script with many optional paths in it, this could take a considerable time, for example a script that searches for all true touches of stedman triples! It is a good idea to choose a single touch you want to prove, or author a script with not too many optional paths in it.

When the command prompt reappears, you can inspect the contents of foundtouches.txt for your new touches.

The program can also take input from the command line and display output in the command prompt window if you just leave out the first or both arguments. Also placing the flags -d and/or -v before the input touch description file name turn on debugging output or verbose touch reporting output respectively. Note that you will only wish to use -d when providing a bug report for eril back to me, which hopefully will not occur too often!

Installation

To install the program, you will need to download the ZIP file referred to on the Web from location: http://www.ropley.com/downloads/eril.zip. Unzip its contents into a working directory for your Eril program, rather like the C:\MyErilFiles folder in the example above. There is a sample copy of the MicroSiril method library, as maintained by Julian Morgan, in the file methods.dat. To construct a more recent one, the batch file mkmeth.bat produces the methods file from a more recent set of MicroSiril method files.

Note too that this program only runs on 32 or 64-bit editions of Windows. If you still have Windows 3 or Windows for Workgroups, consider donating it to the Bletchley computing museum, then buying a machine that was made in this millenium!

Syntax of ERIL composition description files

A touch description is broken into three parts. First, the header describes general properties of the touch, such as the number of bells the touch is rung on, where to find the method library, etc. At the moment, this header only specifies the number of bells as a number followed by a semi-colon.

Second is a sequence of substitution or macro substitution statements. These are described below, but they provide a description of how to expand the touch description into a sequence of place notations.

Lastly come one or more touch specifications themselves. These are the components that are actually proven, one at a time. Note that touch specifications may be interspersed with substitutions and macros, but the macros and substitutions that precede the touch specifications must satisfy all the needs of the touch specifications at the point they appear.

White space and comments

The use of white space characters to make ERIL more readable is possible. White space is not treated as significant. However, white space should not appear within place notation tokens.

Comments are placed after oblique characters '/' and continue to the end of the line on which they appear.

Place notation tokens:

Places are made up from 1234567890ETABCD as increasing valued ordered sets, e.g. 12 or 10 or 367T. Note that omission of a digit/letter at the beginning or end of the set implies the extreme position: On ten bells, 45 means 1450. Placeless (cross-) changes consist of the token ' -', or ' X' (upper case only). The junction between two place notation tokens is denoted by a period '.', but this may be omitted where the junction between two place notations is between a change with places made and a cross-change. Note also that the place letters for elevenths place through sixteenth are accepted in upper case only. Lower case letters are all available for other identifiers.

Block tokens and sequences:

A sequence of place notation tokens may be treated as a unit by linking them with plus ‘+’ symbols. For example: 34-34.16 + -12-16-12-. This is seldom useful on its own as the plus operator has lower precedence than any other operator in Eril. To alter precedence levels, place the sequence in parentheses to make a block token. Block tokens are used where the block needs to be treated as a single entity.

Option tokens:

A choice of place notation or of block may be denoted by the vertical bar symbol '| '. This means that in a backtracking program, each of the options may be tried in turn as part of the proving process. Note that this operator has higher precedence than the plus operator, as demonstrated in the example below of an option of a lead starting with Kent or Oxford places:

34-34|-34- + 16-12-16-12-

Substitution or definition statements:

A new token can be defined that becomes an alias for a sequence of one or more other tokens. This is used to simplify ERIL touch descriptions. The syntax for this is: identifier = token-sequence ; Note that the semi-colon at the end of the sequence marks the end of the substitution statement. Use of semi-colons in this way allows long token sequences to spill across multiple lines. The identifier defined in a substitution may subsequently be used in other statements, including other substitution definitions. Note that the plus symbol between the substituted token and a block of place notation must be present as below. Here is an example:

HalfLeadOfKent = 34-34.16-12-16-12-;

LeadOfKent = HalfLeadOfKent + 16-12-16-12-16.34-34.16;

Reversal statements:

Many (most) methods and principles have place notation symmetry about the middle of a block of changes. A shorthand way of representing a block that is the reverse of another block of place notation is to use the reversal operator '~. Note this is not the same as the reversal operator of the MicroSiril method libraries, where the last place (at the half lead) is not repeated in the reversal, and the whole expansion includes the forward as well as the reversed sequence or places. Eril just provides the reversal of another block via the reversal operator. Example:

HalfLeadOfKent = 34-34.16-12-16-12-;

LeadOfKent = HalfLeadOfKent + 16 + ~HalfLeadOfKent + 16;

Macro statements:

Substitution statements can also be furnished with macro parameters. This allows a standard block to be customised where it occurs in a touch. Example:

method(body, halfLead, leadEnd) = body + halfLead + ~body + leadEnd;
plainBody = -16-16-;
PlainBob = method( plainBody, 16, 12 );
ReverseBob = method( plainBody, 56, 16 );
DoubleBob = method( plainBody, 56, 12 );

Note that recursion in macros, as well as in ordinary substitutions is not permitted. Recursion is where you use the same macro or definition name in the expression to the right of the '=' as appears at the left. Such definitions would expand to have inifinite length, which makes them unprovable.

Method statements:

A method from a method library may be loaded using a fully qualified method name in double quotes. This token expands to be the method's place notation for a single lead of the method. The method name consists of two space-separated strings. Example:

"Cambridge Surprise"; / Expands to a lead of Cambridge found from a method library

Note that methods in a method collection are assumed to have the names and categories as used in the MicroSiril method collections. These are: Plain, TrebleBob, TreblePlace, Surprise, Delight, OddHunt, Principle, Alliance, SlowCourse. The word ‘Plain’ may be omitted in the method name, as this is assumed to be the default if nothing else is specified. If a prior method has been selected from the method collection, its method type becomes the new default for later methods.

Here is an example that searches for certain true courses of Kent and Oxford TB Major where the first and fourth leads can be Kent or Oxford in any combination:

8; / The 1st line specifies the number of bells
K = "Kent TrebleBob"; / These 2 lines are substitution statements
O = "Oxford"; / Still treble bob as current default type
/ The actual touch specification to be proven:
K|O + O + O + K|O + O + O + K;

Repetition:

To indicate repetition of a block, an asterisk followed by the repetition value is used. The repetition value may be a decimal number, or a range enclosed in square brackets. (Note though that the asterisk and repetition value must follow the block to be repeated, and cannot precede it, as this makes the ERIL grammar ambiguous.) Examples:

8;
R = "Rutland Surprise";
CNY = "Cambridge" | "Lincolnshire" | "Yorkshire";
ShortCourse = (CNY*4+R)|(CNY*3+R+CNY)|(CNY*2+R+CNY*2)|(CNY+R+CNY*3)|(R+CNY*4);
/ 5-lead courses of up to four spliced
(R|CNY)*[3-7]; / Finds all true bobless courses of four spliced

Pattern filters:

A common requirement is to specify that at a particular point in a touch the lead should end with a certain pattern. For example, in major, we might be looking for all courses that end with the tenors at Home, or a sequence of plain leads followed by a bob at Wrong. These pattern filters are implemented using the arrow "->" operator as follows:

(p|b|s)*[1-7]->"*78"; / Matches all courses that end with tenors at home

p*[0-6]+b->"*7.8."|"*8.7"; / Makes next call a bob at wrong or middle

The change patterns that follow the arrow operator either begin or end with an asterisk '*', thus representing the first or last several bells of a row, and have single unspecified bells represented by a period '.'

Note that if the entire touch specification ends with a pattern filter, the eril prover searches for any block that ends with that pattern, rather than touches that end with rounds. This is obvious if you think about it, as ending with a pattern that does not include rounds as a pattern match could never yield a true touch. In this way then, eril can be used to search for turning courses for example.

Replacement blocks:

A common requirement is to specify that a method is like another, except for some place changes. This is particularly true if trying to describe a call in a method, where certain rows of place notation get replaced with other rows. Two constructs exist for permitting this. First a construct for representing a block of changes where some of the place notations are not described:

3.123 << 1 / Last two places of a lead will be 3 and 123.
/ The other places are unspecified, as is the length.

567.1.7 >> 1 / First 3 changes of a lead have the specified
/ place notation. The length of the block is undefined.

14 << 0 / Last place of a lead will be 14 as in a normal bob.

What do these tokens actually mean? The expression to the left of the shift symbol (‘<<’ or ‘>>’) is a block of place notation that is destined to replace some of the place notation in the plain lead of a method. The number to the right of the shift symbol tells us where in the plain lead the first place of the replacement block will be applied. If the number has the value '0', then as with most methods this replaces the lead head change. If the number has the value '1', then this would be the first change after the lead head, assuming the shift operator is a right shift ('>>'). If the number is preceded by a left shift ('<<') then the number represents how many places back into the lead before the lead head change the replacement will be applied. Hence for example, the Eril expression: "grandsire" & 3.123 << 1 represents a lead of Grandsire where the penultimate and last change of the lead are replaced with the place notation 3 and 123, thereby forming a traditional Grandsire single.

There is no shorthand for leaving out the shift distance number. The replacement block's only use is after the ‘&’ operator (discussed bleow). The two shift specifiers (‘<<’ and ‘>>’) are each higher precedence than the ‘&’ operator, which in turn has higher precedence than ‘|’.

The grammar rules for Eril require that the thing to the left of the '<<' or '>>' must be a place notation block or a substitution/definition name that represents one. The thing to the right of the '<<' or '>>' must be a positive decimal number (not a definition or macro for one), that lies within one lead length of the item to the left of the '&' operator (discussed immediately below). NOTE: Earlier versions of Eril used a shift number one less for right shifts, where '>>0' was equivalent to the first change into a lead, while '<<0' was the lead head. This was changed to the current form as it was not logical.

To represent a replacement of some of the places in a method with new ones, use the ‘&’ operator as follows. Note that the thing to the left of the '&' operator can be a library method, a '~' expression, a block of place notation, or another '&' expression. It cannot be multi-block expressions like '|' or '+' expressions:

7; / Touch is a touch of Triples
p = "Grandsire"; / Lookup Grandsire Triples from the plain
/ methods collection
Bob = 3.1 << 1; / Place notation alterations to use for a bob
Single = 3.123 << 1; / Place notation alterations to use for a
/ Grandsire single
b = p & Bob; / The place notation for a bobbed lead of
/ Grandsire
s = p & Single; / Likewise for a lead ending with a single
choice = (p|b|s); / What each lead may contain
choice * [3-10]; / All touches from 42 to 140 changes

Note one important feature. If a replacement block is specified for which the number of changes spills over the end of the block, the replacement should also carry on into the next block of changes. Thus variations like April Day (really Reverse St. Bartholomew!) where the call spills into the next lead across a lead end can be readily accommodated, as in the example below. Eril can do this for you. (Note though that there is no way of having the call at the end of a touch automatically wrap back to the first change of the touch):

5;
Plain = "PlainBob";
/ Most plain methods have ‘Bob’
/ in their name in the method library
Bob = Plain & (3.123.3 << 1); / Will spill one change into lead
/ beyond call
Opt = Bob | Plain;
Part = Opt * 3 + Plain;
/ Can't have calls at the last
/ lead in this kind of extent
Part * 3; / Finds all the April Day 120s

Value blocks:

In proving, if an option block occurs several times over, all the options are retried at each point they occur. What a value block does is to allow us to give a name to the latest value of a block already part of the earlier changes in a touch, and to reuse the same values for the options later in the touch. The syntax uses square braces and an optional identifier:

KentOrOxford = [block1 34-34|-34-] + 16-12-16-12-16-12-16-12-16 + block1 + 16;

Note that when used with the repetition operator ‘*’ there is no need to give the value block a name. For example, to represent a whole course of plain leads of Kent or Oxford spliced, use: KentOrOxford*5;. To represent a whole course of either Kent or Oxford (same method every lead), use: [KentOrOxford]*5.

8;
k = "Kent TrebleBob";
o = "Oxford";
lead = k|o;
[lead]*7;
/ A whole course of either Kent or Oxford

Some examples of touch descriptions

To show the expressiveness of this as a touch description language, here are some simple examples. The first example is a standard 720 of Plain Bob Minor. Notice how the macro substitutes an entire plain lead of the method with a copy of the plain lead of the method in this format, thereby still having the desired effect:

6;
pb = "PlainBob";
p = 12<<0;
b = 14<<0;
s = 1234<<0;
course(wrong, home) = pb & wrong + pb*3 + pb & home;
part(lastCall) = course(b, b) + course(b, lastCall);
halfExtent = part(p) + part(p) + part(s);
halfExtent*2;

Second example: A search for all touches of Plain Bob Minor that are made of bobs or singles at Wrong and Home, and Singles at Before, and that have between six and twelve calls:

6;
p = "PlainBob";
b = p&14<<0;
s = p&1234<<0;
plains = p*[0-4];
call(whichCall, music) = plains + whichCall->music;
wrong(bobOrSingle) = call(bobOrSingle, "*6.");
sbefore = call(s, "16*");
home(bobOrSingle) = call(bobOrSingle, "*6");
(wrong(b|s)|sbefore|home(b|s))*[6-12]+plains;

Footnotes

The Eril parser generates a 2.5 Mb file the first time it is run. If you leave the file alone, each successive time Eril is started it will initialise much faster. If you delete it, it will take several extra seconds recreating it next time you run the program. What this file contains is a table for every Major change and which change to go to next for a given place notation. It is used internally to prove touches on fewer than 9 bells at lightning speed!

S D Smith - April 2000