8. Procedures
Formal
grammars may be seen as declarative descriptions of string languages. A
frequently raised question addresses the possibility of encapsulating
procedural
knowledge
into declarative knowledge.
In a formal grammar this may be accomplished by "flags" (see "Programmed grammars",
QuickStart §11) or by other procedures, see for instance "Destroying
structures"
§4.5.
Here
we deal with
procedures
that may be inserted in subgrammar rules. Every procedure name starts with an
underline character. Current procedures are
_destru
_goto
_failed
_repeat
_stop
that
control derivations, and
_print
_printOn
_printOff
_stepOn
_stepOff
_traceOn
_traceOff
that
modify the trace output, not the derivation itself.
Note
that the names of procedures are not case-sensitive. Thus, for example,
"_traceOn" may be equivalently written "_Traceon", "_TRACEON", etc.
If
a procedure appears in the left argument of a rule
it is executed before the rule is applied. If it appears in the right argument
it is executed once the rule has been applied. Trace procedures, _destru
and _stop
may appear on either side, but _goto,
_failed
and _repeat
must only appear in the right argument of a rule. Procedures
in the left argument should be placed after weights and flags, and before any
variables or terminal symbols. Procedures in the right argument should be
placed after variables or terminal symbols.
8.1 Production
procedures
_destru
works exactly as described in §4.5, but it will only be performed if the
rule in which it appears is a candidate rule.
_goto
is an unconditional jump to another subgrammar or another specific rule in a
subgrammar. Its syntax is
_goto(igram,irul)
where
igram
is the index of the destination grammar and
irul
the index of the destination rule. In case irul = 0, BP2 will jump to
subgrammar
igram
and look for any candidate rule. If (igram,irul) does not point at a candidate
rule, BP2 will either execute a _failed conditional jump (see infra) or search
a candidate rule in subgrammar
igram.
If none is found it will jump to subgrammar igram+1, etc. as usual.
When
compiling the grammar BP2 will check that there is a rule indexed
irul
in subgrammar
igram.
If there is no such rule an error will be reported.
_failed
is a conditional jump to another subgrammar or another specific rule in a
subgrammar. Its syntax is
_failed(igram,irul)
in
which
igram
and
irul
have the same meanings as in _goto. The jump will be performed if the rule was
selected by a preceding _goto or _failed and it was not a
candidate
rule.
_repeat
is
a loop. Its simplest syntax is
_repeat(n)
where
n
is an integer value indicating that the current rule should be tried
n
times.
Alternate syntaxes are
_repeat(Kx)
and _repeat(Kx = n)
where
Kx is a
parameter
that may be assigned a fixed value (Kx = n) and/or controlled in real time by
an external MIDI device (see QuickStart §6). Remember that fixed value
assignment must be done only once in the entire grammar.
Both
_repeat and _goto may appear in the same rule, e.g.:
X
--> a b _repeat(12) _goto(4,8)
In
this case, _goto(4,8) will be performed once the rule has been applied 12 times
or it is no longer candidate.
See
example "-gr.tryrepeat"
for important remarks.
8.2 Trace
procedures
_stop
makes a pause. The "Resume/stop" window is displayed.
_print
displays the work string in the "Trace" window.
_printOn
and
_printOff
set the "Display computation" mode on and off respectively. Similarly,
_traceOn
and
_traceOff
set the "Trace computation" mode on and off respectively, while
_stepOn
and
_stepOff
do the same with the "Step computation" mode.
8.3 Renumbering
and remapping conditional jumps
If
the grammar has been successfully compiled once, grammar and rule indexes have
been inserted in the leftmost part of each rule. This part serves as an
identification header. If you need to displace a rule, cut and paste it along
with its identification header
without
changing its arguments
.
When
recompiling the grammar, BP2 will renumber rules and subgrammars, and
eventually modify identification headers and arguments in _goto and _failed
procedures. Consider for example grammar "-gr.tryGOTO":
-ho.abc
-se.tryGOTO
[This
grammar generates a string containing...]
[...
not more than six 'c' and an equal...]
[...
number of 'a' and 'b'.]
ORD
GRAM#1[1]
S --> X S _repeat(K1=12) _goto(1,2)
GRAM#1[2]
S --> lambda _goto(2,0)
----------
RND
_print
GRAM#2[1]
<5-1> X --> C
GRAM#2[2]
<1> X --> C _goto(3,1)
----------
RND
GRAM#3[1]
X --> A _failed(4,0) _goto(3,2)
GRAM#3[2]
X --> B _failed(3,3) _goto(3,1)
GRAM#3[3]
_print ? --> ? B _goto(4,0) _print _stop
----------
SUB
GRAM#4[1]
A --> a
GRAM#4[2]
B --> b
GRAM#4[3]
C --> c
Suppose
that rule [3] of subgrammar #3 is displaced as follows:
----------
RND
GRAM#3[3]
_print ? --> ? B _goto(4,0) _print _stop
GRAM#3[1]
X --> A _failed(4,0) _goto(3,2)
GRAM#3[2]
X --> B _failed(3,3) _goto(3,1)
----------
After
recompiling subgrammar #3 will be:
----------
RND
GRAM#3[1]
_print ? --> ? B _goto(4,0) _print _stop
GRAM#3[2]
X --> A _failed(4,0) _goto(3,3)
GRAM#3[3]
X --> B _failed(3,1) _goto(3,2)
----------
Let
us now study "-gr.tryGOTO".
The first subgrammar is an "ORD" grammar therefore rules are tried in order.
Rule [1] will be applied 12 times, then rule [2] will be applied so that 'S'
will be erased. (Since it is controlled by K1 the number of repetitions may be
later modified by a MIDI device.) The workstring will then be displayed
because there is a "_print" on top of subgrammar #2. Then rule [1] or [2] of
subgrammar #2 will be applied, with a strong preference for [1] which has an
initial weight <5>. Whenever rule [2] is applied BP2 will jump to rule
[1] of subgrammar #3. If the rule is not candidate, the "_failed" procedure
will force it to jump to subgrammar 4. Otherwise, rules [1] and [2] will be
applied alternately. If rule [2] of subgrammar #3 is no longer candidate, rule
[3] will be applied once (producing an extra 'b'), then "_goto(4,0)" will force
a jump to subgrammar #4. The rest needs no explanation. It is easy to check
that the numbers of 'a' and 'b' will eventually be equal.
Indeed,
this is an extreme case in which there is so much procedural control that the
grammar appears almost like a program (in any procedural language).
Nevertheless, it demonstrates BP2's ability to combine procedural with
declarative knowledge.