BadScript 2
Loading...
Searching...
No Matches
TokenPartitioner.cs
Go to the documentation of this file.
1// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
2
3using System;
4using System.Collections.Generic;
5using System.Linq;
6
8
9using CSharpx;
10
11namespace CommandLine.Core
12{
13 internal static class TokenPartitioner
14 {
15 public static
16 Tuple<IEnumerable<KeyValuePair<string, IEnumerable<string>>>, IEnumerable<string>, IEnumerable<Token>>
17 Partition(IEnumerable<Token> tokens,
18 Func<string, Maybe<TypeDescriptor>> typeLookup)
19 {
20 IEqualityComparer<Token> tokenComparer = ReferenceEqualityComparer.Default;
21
22 IEnumerable<Token> tokenList = tokens.Memoize();
23
24 Tuple<IEnumerable<Token>, IEnumerable<Token>, IEnumerable<Token>, IEnumerable<Token>> partitioned =
25 PartitionTokensByType(tokenList, typeLookup);
26 IEnumerable<Token> switches = partitioned.Item1;
27 IEnumerable<Token> scalars = partitioned.Item2;
28 IEnumerable<Token> sequences = partitioned.Item3;
29 IEnumerable<Token> nonOptions = partitioned.Item4;
30
31 Tuple<IEnumerable<Token>, IEnumerable<Token>> valuesAndErrors =
32 nonOptions.PartitionByPredicate(v => v.IsValue());
33 IEnumerable<Token> values = valuesAndErrors.Item1;
34 IEnumerable<Token> errors = valuesAndErrors.Item2;
35
36 return Tuple.Create(KeyValuePairHelper.ForSwitch(switches)
37 .Concat(KeyValuePairHelper.ForScalar(scalars))
38 .Concat(KeyValuePairHelper.ForSequence(sequences)),
39 values.Select(t => t.Text),
40 errors
41 );
42 }
43
44 public static Tuple<IEnumerable<Token>, IEnumerable<Token>, IEnumerable<Token>, IEnumerable<Token>>
45 PartitionTokensByType(IEnumerable<Token> tokens,
46 Func<string, Maybe<TypeDescriptor>> typeLookup)
47 {
48 List<Token> switchTokens = new List<Token>();
49 List<Token> scalarTokens = new List<Token>();
50 List<Token> sequenceTokens = new List<Token>();
51 List<Token> nonOptionTokens = new List<Token>();
52 Dictionary<Token, IList<Token>> sequences = new Dictionary<Token, IList<Token>>();
53 Dictionary<Token, int> count = new Dictionary<Token, int>();
54 Dictionary<Token, Maybe<int>> max = new Dictionary<Token, Maybe<int>>();
55 SequenceState state = SequenceState.TokenSearch;
56 bool separatorSeen = false;
57 Token nameToken = null;
58
59 foreach (Token token in tokens)
60 {
61 if (token.IsValueForced())
62 {
63 separatorSeen = false;
64 nonOptionTokens.Add(token);
65 }
66 else if (token.IsName())
67 {
68 separatorSeen = false;
69
70 if (typeLookup(token.Text)
71 .MatchJust(out TypeDescriptor info))
72 {
73 switch (info.TargetType)
74 {
75 case TargetType.Switch:
76 nameToken = null;
77 switchTokens.Add(token);
78 state = SequenceState.TokenSearch;
79
80 break;
81 case TargetType.Scalar:
82 nameToken = token;
83 scalarTokens.Add(nameToken);
84 state = SequenceState.ScalarTokenFound;
85
86 break;
87 case TargetType.Sequence:
88 nameToken = token;
89
90 if (!sequences.ContainsKey(nameToken))
91 {
92 sequences[nameToken] = new List<Token>();
93 count[nameToken] = 0;
94 max[nameToken] = info.MaxItems;
95 }
96
97 state = SequenceState.SequenceTokenFound;
98
99 break;
100 }
101 }
102 else
103 {
104 nameToken = null;
105 nonOptionTokens.Add(token);
106 state = SequenceState.TokenSearch;
107 }
108 }
109 else
110 {
111 switch (state)
112 {
113 case SequenceState.TokenSearch:
114 case SequenceState.ScalarTokenFound when nameToken == null:
115 case SequenceState.SequenceTokenFound when nameToken == null:
116 separatorSeen = false;
117 nameToken = null;
118 nonOptionTokens.Add(token);
119 state = SequenceState.TokenSearch;
120
121 break;
122
123 case SequenceState.ScalarTokenFound:
124 separatorSeen = false;
125 nameToken = null;
126 scalarTokens.Add(token);
127 state = SequenceState.TokenSearch;
128
129 break;
130
131 case SequenceState.SequenceTokenFound:
132 if (sequences.TryGetValue(nameToken, out IList<Token> sequence))
133 {
134 if (max[nameToken]
135 .MatchJust(out int m) &&
136 count[nameToken] >= m)
137 {
138 // This sequence is completed, so this and any further values are non-option values
139 nameToken = null;
140 nonOptionTokens.Add(token);
141 state = SequenceState.TokenSearch;
142 }
143 else if (token.IsValueFromSeparator())
144 {
145 separatorSeen = true;
146 sequence.Add(token);
147 count[nameToken]++;
148 }
149 else if (separatorSeen)
150 {
151 // Previous token came from a separator but this one didn't: sequence is completed
152 separatorSeen = false;
153 nameToken = null;
154 nonOptionTokens.Add(token);
155 state = SequenceState.TokenSearch;
156 }
157 else
158 {
159 sequence.Add(token);
160 count[nameToken]++;
161 }
162 }
163 else
164 {
165 // Should never get here, but just in case:
166 separatorSeen = false;
167 sequences[nameToken] = new List<Token>(new[] { token });
168 count[nameToken] = 0;
169 max[nameToken] = Maybe.Nothing<int>();
170 }
171
172 break;
173 }
174 }
175 }
176
177 foreach (KeyValuePair<Token, IList<Token>> kvp in sequences)
178 {
179 if (kvp.Value.Empty())
180 {
181 nonOptionTokens.Add(kvp.Key);
182 }
183 else
184 {
185 sequenceTokens.Add(kvp.Key);
186 sequenceTokens.AddRange(kvp.Value);
187 }
188 }
189
190 return Tuple.Create((IEnumerable<Token>)switchTokens,
191 (IEnumerable<Token>)scalarTokens,
192 (IEnumerable<Token>)sequenceTokens,
193 (IEnumerable<Token>)nonOptionTokens
194 );
195 }
196
197#region Nested type: SequenceState
198
199 private enum SequenceState
200 {
204 }
205
206#endregion
207 }
208}
The Maybe type models an optional value. A value of type Maybe a either contains a value of type a (r...
Definition Maybe.cs:33
static IEnumerable< KeyValuePair< string, IEnumerable< string > > > ForSwitch(IEnumerable< Token > tokens)
static IEnumerable< KeyValuePair< string, IEnumerable< string > > > ForScalar(IEnumerable< Token > tokens)
static IEnumerable< KeyValuePair< string, IEnumerable< string > > > ForSequence(IEnumerable< Token > tokens)
static Tuple< IEnumerable< Token >, IEnumerable< Token >, IEnumerable< Token >, IEnumerable< Token > > PartitionTokensByType(IEnumerable< Token > tokens, Func< string, Maybe< TypeDescriptor > > typeLookup)
static Tuple< IEnumerable< KeyValuePair< string, IEnumerable< string > > >, IEnumerable< string >, IEnumerable< Token > > Partition(IEnumerable< Token > tokens, Func< string, Maybe< TypeDescriptor > > typeLookup)