@@ -74,31 +74,34 @@ 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, look ahead to the next token ` t' ` in ` M ` , i.e. ` t' = HEAD(TAIL(M)) `
83
+ 1 . If ` TAIL(M) ` was empty, check that parameter ` F ` is a subset of ` FOLLOW(t) ` . If so, skip to #6 , else, reject.
84
+ 2 . Otherwise, check that ` t' ` is in ` FOLLOW(t) ` . If so, skip to #6 , else, reject.
85
+ 5 . Else, ` t ` is a complex NT.
86
+ 1 . If ` t ` has the form ` $(Q)+ ` or ` $(Q)* ` , run ` CHECK(Q, LEADERS(TAIL(M)) ` , i.e. with ` F `
87
+ being the set of all possible successors of ` t ` in ` M ` . If it accepts, continue, else, reject.
88
+ 2 . If ` t ` has the form ` $(Q)u+ ` or ` $(Q)u* ` for some token ` u ` , run
89
+ ` CHECK(Q, {u}) ` . If it accepts, continue, else, reject.
90
+ 6 . Set ` M = TAIL(M) ` .
91
+
92
+ ` LEADERS(S): ` Returns the set of all possible tokens that may begin input sequence matched by ` S ` .
93
+ 1 . If ` S ` is empty, return ` {} ` .
94
+ 2 . Set ` t = HEAD(S) `
95
+ 3 . If ` t ` is not a complex NT, return ` {t} ` .
96
+ 4 . If ` t ` is a complex NT:
97
+ 1 . If ` t ` has the form ` $(Q)+ ` or ` $(Q)u+ ` , return ` LEADERS(Q) ` .
98
+ 2 . If ` t ` has the form ` $(Q)* ` or ` $(Q)u* ` , return ` LEADERS(Q) U LEADERS(TAIL(S)) ` .
99
+
100
+ ` HEAD(M) ` Returns the first token in sequence ` M ` .
101
+ ` TAIL(M) ` Returns sequence ` M ` with the first token removed.
99
102
100
103
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
104
+ invocation, with ` F ` as ` {} ` . If it rejects a matcher, an error should be
102
105
emitted and compilation should not complete.
103
106
104
107
The current legal fragment specifiers are: ` item ` , ` block ` , ` stmt ` , ` pat ` ,
@@ -115,7 +118,7 @@ The current legal fragment specifiers are: `item`, `block`, `stmt`, `pat`,
115
118
- ` FOLLOW(item) ` = any token
116
119
- ` FOLLOW(meta) ` = any token
117
120
118
- (Note that close delimiters are valid following any NT.)
121
+ (Note that open and close delimiters are valid following any NT.)
119
122
120
123
# Drawbacks
121
124
0 commit comments