Sub-rules
Definition and references
A sub-rule is a portion of rule that does not get evaluated by itself but can be referenced, by name, in other rules.
Sub-rules are useful when you have several rules with some common parts, because they avoid writing these parts multiple times. This also helps reduce the occurrence of errors.
A sub-rule can either be used in a rule as the only element constituting the condition or combined with other attributes using for example boolean operators.
For example, consider this rule:
SCOPE SENTENCE
{
DOMAIN(dom1:NORMAL)
{
ANCESTOR(12828) /*12828: plane, aeroplane, airplane*/
AND
LEMMA("hijack")
AND NOT
(
LEMMA ("fiction") > LEMMA("story")
OR
ANCESTOR(30419, 30451)// 30419: film, movie // 30451: television show, television program
OR
SYNCON(29428,18571)// 29428: novel (genre) 18571: novel (physical object);
)
}
}
If you have more rules sharing the part of the condition highlighted in yellow, you can define a sub-rule like this:
#fiction# = LEMMA ("fiction") > LEMMA("story")
OR
ANCESTOR(30419, 30451)// 30419: film, movie // 30451: television show, television program
OR
SYNCON(29428,18571)// 29428: novel (genre) 18571: novel (physical object)
;
and then you can refer to it by its name in other rules:
SCOPE SENTENCE
{
DOMAIN(dom1:NORMAL)
{
ANCESTOR(12828) /*12828: plane, aeroplane, airplane*/
AND
LEMMA("hijack")
AND NOT
#fiction#
}
}
The syntax of the sub-rule definition is:
#sub-ruleName# = sub-rule;
Or, alternatively:
#sub-ruleName#
=
sub-rule
;
where sub-ruleName
is the name of the sub-rule. The semi-colon at the end is a mandatory terminator.
Warning
If you write comments:
- Between the sub-rule name and the equal sign (
=
).
Or:
- Between the equal sign (
=
) and the sub-rule.
an error will occur.
Sub-rules must be defined before being referenced.
It's advisable to define them at the beginning of the rules file or in a separate .cr file that is imported in the main rules file.
There are two different syntaxes to refer to a sub-rule in a rule:
##sub-ruleName##
And:
#sub-ruleName#
In the first case it is as if the sub-rule was written verbatim in the rule.
In the second case it is as if round brackets were automatically added around the sub-rule, i.e. you don't have to write them in the sub-rule or in the rules referencing it.
The following is an example of rules in which to adopt the first syntax:
SCOPE scopeOption
{
DOMAIN(domainName:scoreOption) | IDENTIFY(templateName)
{
operand
positionalSequence | logicalOperator
##sub-ruleName##
}
}
And this is an example of rules in which to adopt the second syntax:
SCOPE scopeOption
{
DOMAIN(domainName:scoreOption) | IDENTIFY(templateName)
{
operand
booleanOperator
#sub-ruleName#
}
}
Automatic parentheses help evaluating Boolean sub-expressions with the correct precedence order.
Combination of sub-rules
Sub-rules can contain references to other sub-rules, given referenced sub-rules are defined before the sub-rule referring to them.
For example:
#date_and_hour# = TYPE(DAT)
<>
TYPE(HOU)
;
#fiction# = LEMMA ("fiction") > LEMMA("story"),
ANCESTOR(30419, 30451),// 30419: film, movie // 30451: television show, television program
SYNCON(29428,18571)// 29428: novel (genre) 18571: novel (physical object)
;
#fiction_date_and_hour# = ##date_and_hour##, ##fiction##;
SCOPE SENTENCE
{
DOMAIN(dom1)
{
ANCESTOR(12828) /*12828: plane, aeroplane, airplane*/
AND
LEMMA("hijack")
<>
MANDATORY
{
##fiction_date_and_hour##
}
}
}
In the sub-rule definition you can use two hashes (verbatim expansion) or one hash (automatic addition of surrounding parentheses) syntax for sub-rules placeholders.
Other applications of sub-rules
Being portions of rules, sub-rules applications are not limited to conditions.
The example below shows an application to rules that use segments.
Sub-rules can also be used with segments.
For example:
SEGMENTS
{
@SEGMENT1,
@SEGMENT2,
@SEGMENT3
}
SCOPE SENTENCE
{
SEGMENT(SEGMENT1)
{
LEMMA("storm", "snowfall", "tornado", "hurricane")
}
SEGMENT(SEGMENT2)
{
ANCESTOR(102221906)//@SYN: #102221906# [place]
}
SEGMENT(SEGMENT3)
{
TYPE(ADJ)
}
}
#SEGMENTS_TO_NEGATE# = SEGMENT1, SEGMENT2, SEGMENT3;
SCOPE SENTENCE IF NOT IN SEGMENT(##SEGMENTS_TO_NEGATE##)
{
DOMAIN(dom1)
{
LEMMA("destroy")
}
}
Sub-rules and boolean operators
As stated above, when you write sub-rules using this syntax:
##sub-ruleName##
it is as if the sub-rule was written verbatim in the rule.
For this reason, pay attention when you combine a sub-rule of this type with boolean operators inside it.
A rule like this:
#fiction# = LEMMA ("fiction") > LEMMA("story")
OR
LEMMA("book")
OR
LEMMA("film", "television show")
OR
SYNCON(29428,18571)// 29428: novel (genre) 18571: novel (physical object)
;
SCOPE SENTENCE
{
DOMAIN(dom1:NORMAL)
{
ANCESTOR(12828) /*12828: plane, aeroplane, airplane*/
AND
LEMMA("hijack")
<>
##fiction##
}
}
is the same as:
SCOPE SENTENCE
{
DOMAIN(dom1:NORMAL)
{
ANCESTOR(12828) /*12828: plane, aeroplane, airplane*/
<1:4>
LEMMA("hijack")
<>
LEMMA ("fiction") > LEMMA("story")
OR
LEMMA("book")
OR
LEMMA("film", "television show")
OR
SYNCON(29428,18571)// 29428: novel (genre) 18571: novel (physical object)
}
}
As you can see, only the first operand of the sub-rule is related to the portion of rule before the positional sequence.
To correctly relate all the sub-rule operands to the portion of rule before the positional sequence, use the MANDATORY
operator, like this:
#fiction# = MANDATORY
{
LEMMA ("fiction") > LEMMA("story"),
LEMMA("book"),
LEMMA("film", "television show"),
SYNCON(29428,18571)// 29428: novel (genre) 18571: novel (physical object)
};
SCOPE SENTENCE
{
DOMAIN(dom1:NORMAL)
{
ANCESTOR(12828) /*12828: plane, aeroplane, airplane*/
<1:4>
LEMMA("hijack")
<>
##fiction##
}
}