@@ -74,31 +74,35 @@ The algorithm for recognizing valid matchers `M` follows. Note that a matcher
74
74
is merely a token tree. A "simple NT" is an NT without repetitions. That is,
75
75
` $foo:ty ` is a simple NT but ` $($foo:ty)+ ` is not. ` FOLLOW(NT) ` is the set of
76
76
allowed tokens for the given NT's fragment specifier, and is defined below.
77
- ` F ` is used for representing the separator in complex NTs. In ` $($foo:ty),+ ` ,
78
- ` F ` would be ` , ` , and for ` $($foo:ty)+ ` , ` F ` would be ` EOF ` .
79
77
80
- * input* : a token tree ` M ` representing a matcher and a token ` F `
81
-
82
- * output* : whether M is valid
83
-
84
- For each token ` T ` in ` M ` :
85
-
86
- 1 . If ` T ` is not an NT, continue.
87
- 2 . If ` T ` is a simple NT, look ahead to the next token ` T' ` in ` M ` . If
88
- ` T' ` is ` EOF ` or a close delimiter of a token tree, replace ` T' ` with
89
- ` F ` . If ` T' ` is in the set ` FOLLOW(NT) ` , ` T' ` is EOF, or ` T' ` is any close
90
- delimiter, continue. Otherwise, reject.
91
- 3 . Else, ` T ` is a complex NT.
92
- 1 . If ` T ` has the form ` $(...)+ ` or ` $(...)* ` , run the algorithm on the
93
- contents with ` F ` set to the token following ` T ` . If it accepts,
94
- continue, else, reject.
95
- 2 . If ` T ` has the form ` $(...)U+ ` or ` $(...)U* ` for some token ` U ` , run
96
- the algorithm on the contents with ` F ` set to ` U ` . If it accepts,
97
- check that the last token in the sequence can be followed by ` F ` . If
98
- so, accept. Otherwise, reject.
78
+ ` CHECK(M, F): ` * input* : a sequence of tokens ` M ` and a set of tokens ` F ` ; * output* : whether M is valid.
79
+ 1 . If ` M ` is empty, accept.
80
+ 2 . Set ` t = HEAD(M) `
81
+ 3 . If ` t ` is not an NT, skip to #6 .
82
+ 4 . If ` t ` is a simple NT:
83
+ 1 . If ` TAIL(M) ` is empty, check that parameter ` F ` is a subset of ` FOLLOW(t) ` . If so, skip to #6 , else, reject.
84
+ 2 . Otherwise, find ` G ` , the set of possible successors of ` t ` in ` M ` : ` G = LEADERS(TAIL(M)) `
85
+ Check that ` G ` is a subset of ` FOLLOW(t) ` . If so, skip to #6 , else, reject.
86
+ 5 . Else, ` t ` is a complex NT.
87
+ 1 . If ` t ` has the form ` $(Q)+ ` or ` $(Q)* ` , run ` CHECK(Q, LEADERS(TAIL(M)) ` , i.e. with ` F `
88
+ being the set of all possible successors of ` t ` in ` M ` . If it accepts, continue, else, reject.
89
+ 2 . If ` t ` has the form ` $(Q)u+ ` or ` $(Q)u* ` for some token ` u ` , run
90
+ ` CHECK(Q, {u}) ` . If it accepts, continue, else, reject.
91
+ 6 . Set ` M = TAIL(M) ` .
92
+
93
+ ` LEADERS(S): ` Returns the set of all possible tokens that may begin input sequence matched by ` S ` .
94
+ 1 . If ` S ` is empty, return ` {} ` .
95
+ 2 . Set ` t = HEAD(S) `
96
+ 3 . If ` t ` is not a complex NT, return ` {t} ` .
97
+ 4 . If ` t ` is a complex NT:
98
+ 1 . If ` t ` has the form ` $(Q)+ ` or ` $(Q)u+ ` , return ` LEADERS(Q) ` .
99
+ 2 . If ` t ` has the form ` $(Q)* ` or ` $(Q)u* ` , return ` LEADERS(Q) U LEADERS(TAIL(S)) ` .
100
+
101
+ ` HEAD(M) ` Returns the first token in sequence ` M ` .
102
+ ` TAIL(M) ` Returns sequence ` M ` with the first token removed.
99
103
100
104
This algorithm should be run on every matcher in every ` macro_rules `
101
- invocation, with ` F ` as ` EOF ` . If it rejects a matcher, an error should be
105
+ invocation, with ` F ` as ` {} ` . If it rejects a matcher, an error should be
102
106
emitted and compilation should not complete.
103
107
104
108
The current legal fragment specifiers are: ` item ` , ` block ` , ` stmt ` , ` pat ` ,
@@ -115,7 +119,7 @@ The current legal fragment specifiers are: `item`, `block`, `stmt`, `pat`,
115
119
- ` FOLLOW(item) ` = any token
116
120
- ` FOLLOW(meta) ` = any token
117
121
118
- (Note that close delimiters are valid following any NT.)
122
+ (Note that open and close delimiters are valid following any NT.)
119
123
120
124
# Drawbacks
121
125
0 commit comments