[Next] [Previous] [Up] [Top] [Contents] [Index]
10 Macros
Patterns
Approximately speaking, a pattern looks like the construct that it matches, but contains pattern variables that bind to portions of the construct. Hence a left-hand side in the main-rule-set looks like a macro call. However, the grammar of patterns is not the same as the grammar of programs, but contains just what is required to match the portions of the Dylan grammar that are extensible by macros. Patterns have a simple nested grammar, with semicolons, commas, and brackets used to indicate levels of nesting. See the definition of pattern in Appendix A, "BNF."
A pattern matches a fragment (a sequence of elementary fragments) by executing the following algorithm from left to right. It is easy to create patterns that are ambiguous when considered as grammars. This ambiguity is resolved by the left to right processing order and the specified try-shortest-first order for matching wildcards. Pattern matching succeeds only if all sub-patterns match. If pattern matching fails, the current rule fails and control passes to the next rule in the current rule set. If all patterns in a rule set fail to match, the macro call is invalid.
Multiple occurrences of the same pattern variable name in a single rule's left-hand side are not valid.
A pattern matches a fragment as follows:
- If the pattern consists of just one pattern-list, go to the next step. Otherwise divide the pattern into subpatterns and the fragment into subfragments at semicolons, and match subpatterns to subfragments individually in order. The subpatterns and subfragments do not include the semicolons that separate them. Suppose the pattern consists of N + 1 pattern-lists separated by N semicolons. Locate the first N semicolons in the fragment (without looking inside of elementary fragments) and divide up the fragment into subfragments accordingly. The match fails if the fragment contains fewer than N - 1 semicolons. As a special case, if the fragment contains N - 1 semicolons, the match still succeeds and the last subfragment is empty. If the fragment contains more than N semicolons, the extra semicolons will be in the last subfragment.
A pattern-list matches a fragment as follows:
- If the pattern-list consists of just a pattern-sequence, go to the next step. If the pattern-list consists of just a property-list-pattern, go to that step. Otherwise divide the pattern-list into subpatterns and the fragment into subfragments at commas, and match subpatterns to subfragments individually in order. The subpatterns and subfragments do not include the commas that separate them. Suppose the pattern consists of N + 1 subpatterns separated by N commas. Locate the first N commas in the fragment (without looking inside of elementary fragments) and divide up the fragment into subfragments accordingly. The match fails if the fragment contains fewer than N - 1 commas. As a special case, if the fragment contains N - 1 commas, the match still succeeds and the last subfragment is empty. If the fragment contains more than N commas, the extra commas will be in the last subfragment. Note that the subdivision algorithms for commas and semicolons are identical.
A pattern-sequence matches a fragment as follows:
- Consider each simple-pattern in the pattern-sequence in turn from left to right. Each simple-pattern matches an initial subsequence of the fragment and consumes that subsequence, or fails. The entire pattern match fails if any simple-pattern fails, if the fragment is empty and the simple-pattern requires one or more elementary fragments, or if the fragment is not entirely consumed after all simple-patterns have been matched. There is a special backup and retry rule for wildcards, described below.
A simple-pattern matches a fragment as follows:
- A name or
=>
consumes one elementary fragment, which must be identical to the simple-pattern. A name matches a name that is spelled the same, independent of modules, lexical scoping issues, alphabetic case, and backslash quoting. As a special case, after the word otherwise
, an =>
is optional in both the pattern and the fragment. Presence or absence of the arrow in either place makes no difference to matching.
- A bracketed-pattern matches and consumes a bracketed-fragment. If the enclosed pattern is omitted, the enclosed body-fragment must be empty, otherwise the enclosed pattern must match the enclosed body-fragment (which can be empty). The type of brackets (
()
, []
, or {}
) in the bracketed-fragment must be the same as the type of brackets in the bracketed-pattern.
A binding-pattern matches a fragment as follows:
- pattern-variable
::
pattern-variable consumes as much of the fragment as can be parsed by the grammar for variable. It matches the first pattern-variable to the variable-name and the second to the type, a parsed expression fragment. If no specializer is present, it matches the second pattern-variable to a parsed expression fragment that is a named value reference to <object>
in the Dylan module. This matching checks the constraints on the pattern variable, fails if the constraint is not satisfied, and binds the pattern variable to the fragment.
- pattern-variable
=
pattern-variable consumes as much of the fragment as can be parsed by the grammar for variable =
expression. It matches the first pattern-variable to the variable, a fragment, and the second to the expression, a parsed expression fragment.
- pattern-variable
::
pattern-variable =
pattern-variable consumes as much of the fragment as can be parsed by the grammar for variable =
expression. It matches the first two pattern-variables the same as the first kind of binding-pattern and it matches the third pattern-variable the same as the second kind of binding-pattern.
A pattern-variable matches a fragment as follows:
- When the constraint is a wildcard constraint (see "Pattern Variable Constraints" on page 154), the pattern variable consumes some initial subsequence of the fragment, using a backup and retry algorithm. First, the wildcard consumes no elementary fragments, and matching continues with the next simple-pattern in the pattern-sequence. If any simple-pattern in the current pattern-sequence fails to match, back up to the wildcard, consume one more elementary fragment than before, and retry matching the rest of the pattern-sequence, starting one elementary fragment to the right of the previous start point. Once the entire pattern-sequence has successfully matched, the pattern variable binds to a fragment consisting of the sequence of elementary fragments that it consumed.
- It is an error for more than one of the simple-patterns directly contained in a pattern-sequence to be a wildcard.
- When the constraint is other than a wildcard constraint, the pattern variable consumes as much of the fragment as can be parsed by the grammar specified for the constraint in "Pattern Variable Constraints" on page 154. If the parsing fails, the pattern match fails. The pattern variable binds to the fragment specified in "Pattern Variable Constraints." This can be a parsed fragment rather than the original sequence of elementary fragments.
- The ellipsis pattern-variable,
...
, can only be used in an auxiliary rule set. It represents a pattern variable with the same name as the current rule set and a wildcard constraint.
A property-list-pattern matches a fragment as follows:
- Parse the fragment using the grammar for property-listopt . If the parsing fails or does not consume the entire fragment, the pattern match fails.
- If the property-list-pattern contains
#key
and does not contain #all-keys
, the match fails if the symbol part of any property is not the name in some pattern-keyword in the property-list-pattern. Comparison of a symbol to a name is case-insensitive, ignores backslash quoting, and is unaffected by the lexical context of the name.
- If the property-list-pattern contains
#rest
, bind the pattern variable immediately following #rest
to the entire fragment. If the pattern variable has a non-wildcard constraint, parse the value part of each property according to this constraint, fail if the parsing fails or does not consume the entire value part, and substitute the fragment specified in "Pattern Variable Constraints" on page 154 for the value part.
- Each pattern-keyword in the property-list-pattern binds a pattern variable as follows:
- A single question mark finds the first property whose symbol is the name of the pattern-keyword . Comparison of a symbol to a name is case-insensitive, ignores backslash quoting, and is unaffected by the lexical context of the name. If the pattern-keyword has a non-wildcard constraint, parse the property's value according to this constraint, fail if the parsing fails or does not consume the entire value , and bind the pattern variable to the fragment specified in "Pattern Variable Constraints" on page 154. If the pattern-keyword has a wildcard constraint, bind the pattern variable to the property's value .
- A double question mark finds every property with a matching symbol, processes each property's value as for a single question mark, and binds the pattern variable to a sequence of the values, preserving the order of properties in the input fragment. This sequence can only be used with double question mark in a template. Constraint-directed parsing applies to each property value individually.
- If a single question mark pattern-keyword does not find any matching property, then if a default is present, the pattern variable binds to the default expression, otherwise the property is required so the pattern match fails.
- If a double question mark pattern-keyword does not find any matching property, then if a default is present, the pattern variable binds to a sequence of one element, the default expression, otherwise the pattern variable binds to an empty sequence.
- Note: the default expression in a pattern-keyword is not evaluated during macro expansion; it is a parsed expression fragment that is used instead of a fragment from the macro call. The default is not subject to a pattern variable constraint.
Special Rules for Definitions
A list-style definition parses as the core reserved word define
, an optional sequence of modifiers, a define-list-word, and a possibly-empty list-fragment. The left-hand side of a list-style-definition-rule matches this by treating the definition-head as a pattern-sequence and matching it to the sequence of modifiers, and then matching the pattern to the list-fragment. If no definition-head is present, the sequence of modifiers must be empty. If no pattern is present, the list-fragment must be empty. The word define
and the define-list-word do not participate in the pattern match because they were already used to identify the macro being called and because the spelling of the define-list-word might have been changed by renaming the macro during module importing.
A body-style definition parses as the core reserved word define
, an optional sequence of modifiers, a define-body-word, a possibly-empty body-fragment, the core reserved word end
, and optional repetitions of the define-body-word and the name (if any) that is the first token of the body-fragment. The left-hand side of a body-style-definition-rule matches this by treating the definition-head as a pattern-sequence and matching it to the sequence of modifiers, and then matching the pattern to the body-fragment. If no definition-head is present, the sequence of modifiers must be empty. If no pattern is present, the body-fragment must be empty. If the body-fragment ends in a semicolon, this semicolon is removed before matching. The optional semicolon in the rule is just decoration and does not participate in the pattern match. The word define
and the define-body-word do not participate in the pattern match because they were already used to identify the macro being called and because the spelling of the define-body-word might have been changed by renaming the macro during module importing. The word end
and the two optional items following it in the macro call are checked during parsing, and so do not participate in the pattern match.
It is an error for a definition-head to contain more than one wildcard.
Special Rules for Statements
A statement parses as a begin-word, a possibly-empty body-fragment, the core reserved word end
, and an optional repetition of the begin-word. The left-hand side of a statement-rule matches this by matching the pattern to the body-fragment. If the rule does not contain a pattern, the body-fragment must be empty. If the body-fragment ends in a semicolon, this semicolon is removed before matching. The optional semicolon in the rule is just decoration and does not participate in the pattern match. The begin-word does not participate in the pattern match because it was already used to identify the macro being called and because its spelling might have been changed by renaming the macro during module importing. The word end
and the optional item following it in the macro call are checked during parsing, and so do not participate in the pattern match.
Special Rules for Function Macros
A call to a function macro parses as a function-word followed by a parenthesized, possibly-empty body-fragment. The left-hand side of a function-rule matches this by matching the pattern to the body-fragment. If the rule does not contain a pattern, the body-fragment must be empty. The function-word does not participate in the pattern match because it was already used to identify the macro being called and because its spelling might have been changed by renaming the macro during module importing. The parentheses in the rule are just decoration and do not participate in the pattern match.
Dylan Reference Manual - 17 OCT 1995
[Next] [Previous] [Up] [Top] [Contents] [Index]
Generated with Harlequin WebMaker