action
throw catch-name catch-parameter-list
You can use throw
to change the flow of your program. Throw causes execution of your program to jump
to the catch
named in the throw
action. As execution is transferred to the catch
, OmniMark
closes local scopes and releases their resources, ensuring a smooth transfer of control from the throw
to
the catch
.
catch
catch-name must exist in a scope that is currently executing. OmniMark will look for
catch
catch-name first in the current scope. If it does not exist in the current scope, OmniMark
looks for it in the parent scope, and so on. Once catch
catch-name is found, OmniMark closes the
current scope and all intervening scopes as required to reach catch
catch-name. Execution is
then transferred to the catch
clause.
If any of the scopes closed on the way to a catch contain an always
clause, the always
clause will be executed before the scope is closed.
If catch
catch-name is not found, OmniMark raises an error which will be caught by the first
available catch
#program-error
. If there is no catch
#program-error
in the
execution scope, the program will terminate.
Consider the following program:
declare catch my-catch process submit "kqaqpzq" catch #program-error output "Rats!%n" find "a" [any except "z"]* => some-stuff "z" submit some-stuff catch my-catch output "Gotcha!%n" find letter => my-letter throw my-catch when my-letter = "q" catch #program-error output "Ooops!%n"
The program above will output the following:
Ooops! Gotcha! Ooops!
Each line in the output is generated as a result of the attempt to throw
when the letter q
occurs in the scanned data. The first time it occurs, the find
rule is executing as a direct result of
the submit
in the process
rule. The catch
my-catch clause is not in scope,
which creates an error that is caught by catch #program-error
in the next line, resulting in the output of
Ooops!
.
The second time q
is matched, it is as a result of the submit
in the first find
rule. Because catch
my-catch is part of the same scope as that submit
, the
catch
is in scope when the second find
rule matches it. Thus the throw
succeeds and the
catch
clause outputs Gotcha!
.
The final time q
is matched, it is once again as a result of the original submit
and the
catch
is no longer part of the execution scope. Thus we get Ooops!
output again.
If we edit the program to remove the catch #program-error
in the second find
rule, the
behavior will be different:
declare catch my-catch process submit "kqaqpzq" catch #program-error output "Rats!%n" find "a" [ \ "z"]* => some-stuff "z" submit some-stuff catch my-catch output "Gotcha!%n" find letter => my-letter throw my-catch when my-letter = "q"
The program above will output the following:
Rats!
The reason we get only a single Rats!
and no Gotcha
is that the OmniMark-initiated
throw
to #program-error
closes down all enclosing scopes, including the scope in which the
catch
occurs. So after the first q
is matched the rest of the submit
is aborted.
A catch
may be declared to allow you to pass various parameters to the catch when you make a
throw
:
declare catch vowel value string the-vowel process submit "kqaqpzq" catch vowel the-vowel output "Hey, " || the-vowel || " isn't a consonant!%n" find letter => my-letter do unless my-letter matches (ul ["aeiou"]) output "Consonant!%n" else throw vowel my-letter done
You are not required to catch
all the parameters.
If an always
clause contains a throw
, and that always
clause is being executed as part
of the closing of a scope in the process of executing a previous throw
, both throw
s will be
completed. The resulting catch
es will be executed in the order in which they occur in the unwinding of
execution scopes, without regard to the order of throw
s. If the two catch
es occur in the same
lexical scope, the order in which they are executed is indeterminate. You cannot use a new throw
to cancel
the execution of a throw
in progress.
If you throw
in a markup rule and that throw
is not caught in the same markup rule, the entire
parse will be aborted. The next point at which the throw
can be caught is in the scope that initiated the
parse.