@@ -189,68 +189,74 @@ fn validate_argument_order(
189189 // Optional choice didn't match - don't consume, continue
190190 }
191191
192- TagArg :: Var { .. } | TagArg :: String { .. } => {
193- // Simple arguments consume exactly one token
192+ TagArg :: String { .. } => {
193+ // String arguments consume exactly one token
194194 bit_index += 1 ;
195195 }
196196
197- TagArg :: Expr { .. } => {
198- // Expression arguments consume tokens greedily until:
199- // - We hit the next literal keyword (if any)
200- // - We run out of tokens
201- // Must consume at least one token
202-
203- let start_index = bit_index;
204- let next_literal = args[ arg_index + 1 ..] . find_next_literal ( ) ;
197+ TagArg :: Variable { count, .. } | TagArg :: Any { count, .. } => {
198+ match count {
199+ crate :: templatetags:: TokenCount :: Exact ( n) => {
200+ // Consume exactly N tokens
201+ bit_index += n;
202+ }
203+ crate :: templatetags:: TokenCount :: Greedy => {
204+ // Greedy: consume tokens until next literal or end
205+ let start_index = bit_index;
206+ let next_literal = args[ arg_index + 1 ..] . find_next_literal ( ) ;
207+
208+ while bit_index < bits. len ( ) {
209+ if let Some ( ref lit) = next_literal {
210+ if bits[ bit_index] == * lit {
211+ break ; // Stop before the literal
212+ }
213+ }
214+ bit_index += 1 ;
215+ }
205216
206- // Consume tokens greedily until we hit a known literal
207- while bit_index < bits. len ( ) {
208- if let Some ( ref lit) = next_literal {
209- if bits[ bit_index] == * lit {
210- break ; // Stop before the literal
217+ // Ensure we consumed at least one token
218+ if bit_index == start_index {
219+ bit_index += 1 ;
211220 }
212221 }
213- bit_index += 1 ;
214- }
215-
216- // Ensure we consumed at least one token for the expression
217- if bit_index == start_index {
218- bit_index += 1 ;
219222 }
220223 }
221224
222- TagArg :: Assignment { .. } => {
223- // Assignment arguments can appear as:
224- // 1. Single token: var=value
225- // 2. Multi-token: expr as varname
226- // Consume until we find = or "as", or hit next literal
227-
228- let next_literal = args[ arg_index + 1 ..] . find_next_literal ( ) ;
229-
230- while bit_index < bits. len ( ) {
231- let token = & bits[ bit_index] ;
232- bit_index += 1 ;
233-
234- // If token contains =, we've found the assignment
235- if token. contains ( '=' ) {
236- break ;
225+ TagArg :: Assignment { count, .. } => {
226+ match count {
227+ crate :: templatetags:: TokenCount :: Exact ( n) => {
228+ // Consume exactly N tokens
229+ bit_index += n;
237230 }
238231 crate :: templatetags:: TokenCount :: Greedy => {
239232 // Assignment arguments can appear as:
240233 // 1. Single token: var=value
241234 // 2. Multi-token: expr as varname
242235 // Consume until we find = or "as", or hit next literal
243236
244- // If we hit "as", consume the variable name after it
245- if token == "as" && bit_index < bits. len ( ) {
246- bit_index += 1 ; // Consume the variable name
247- break ;
248- }
249-
250- // Stop if we hit the next literal argument
251- if let Some ( ref lit) = next_literal {
252- if token == lit {
253- break ;
237+ let next_literal = args[ arg_index + 1 ..] . find_next_literal ( ) ;
238+
239+ while bit_index < bits. len ( ) {
240+ let token = & bits[ bit_index] ;
241+ bit_index += 1 ;
242+
243+ // If token contains =, we've found the assignment
244+ if token. contains ( '=' ) {
245+ break ;
246+ }
247+
248+ // If we hit "as", consume the variable name after it
249+ if token == "as" && bit_index < bits. len ( ) {
250+ bit_index += 1 ; // Consume the variable name
251+ break ;
252+ }
253+
254+ // Stop if we hit the next literal argument
255+ if let Some ( ref lit) = next_literal {
256+ if token == lit {
257+ break ;
258+ }
259+ }
254260 }
255261 }
256262 }
0 commit comments