|
143 | 143 | // Handle Strings
|
144 | 144 | if (stream.match(stringPrefixes)) {
|
145 | 145 | var isFmtString = stream.current().toLowerCase().indexOf('f') !== -1;
|
146 |
| - if (!isFmtString || state.fstr_state !== null) { |
| 146 | + if (!isFmtString) { |
147 | 147 | // if this is a nested format string (e.g. f' { f"{10*10}" + "a" }' )
|
148 | 148 | // we do not format the nested expression and treat the nested format
|
149 | 149 | // string as regular string
|
150 | 150 | state.tokenize = tokenStringFactory(stream.current());
|
151 | 151 | return state.tokenize(stream, state);
|
152 | 152 | } else {
|
153 | 153 | // need to do something more sophisticated
|
154 |
| - state.tokenize = formatStringFactory(stream.current()); |
| 154 | + state.tokenize = formatStringFactory(stream.current(), state.tokenize); |
155 | 155 | return state.tokenize(stream, state);
|
156 | 156 | }
|
157 | 157 | }
|
|
184 | 184 | return ERRORCLASS;
|
185 | 185 | }
|
186 | 186 |
|
187 |
| - function formatStringFactory(delimiter) { |
| 187 | + function formatStringFactory(delimiter, tokenOuter) { |
188 | 188 | while ("rubf".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)
|
189 | 189 | delimiter = delimiter.substr(1);
|
190 | 190 |
|
191 | 191 | var singleline = delimiter.length == 1;
|
192 | 192 | var OUTCLASS = "string";
|
193 | 193 |
|
194 |
| - function tokenString(stream, state) { |
195 |
| - if (state.fstr_state) { |
196 |
| - // inside f-str Expression |
197 |
| - if (stream.match(delimiter)) { |
198 |
| - // expression ends pre-maturally, but very common in editing |
199 |
| - // Could show error to remind users to close brace here |
200 |
| - state.fstr_state = null; |
201 |
| - return OUTCLASS; |
202 |
| - } else if (stream.match('{')) { |
203 |
| - // starting brace, if not eaten below |
204 |
| - return "punctuation"; |
205 |
| - } else if (stream.match('}')) { |
206 |
| - // return to regular inside string state |
207 |
| - state.fstr_state = null; |
208 |
| - return "punctuation"; |
209 |
| - } else { |
210 |
| - // use tokenBaseInner to parse the expression |
211 |
| - return tokenBaseInner(stream, state.fstr_state); |
212 |
| - } |
| 194 | + function tokenFString(stream, state) { |
| 195 | + // inside f-str Expression |
| 196 | + if (stream.match(delimiter)) { |
| 197 | + // expression ends pre-maturally, but very common in editing |
| 198 | + // Could show error to remind users to close brace here |
| 199 | + state.tokenize = tokenString |
| 200 | + return OUTCLASS; |
| 201 | + } else if (stream.match('{')) { |
| 202 | + // starting brace, if not eaten below |
| 203 | + return "punctuation"; |
| 204 | + } else if (stream.match('}')) { |
| 205 | + // return to regular inside string state |
| 206 | + state.tokenize = tokenString |
| 207 | + return "punctuation"; |
| 208 | + } else { |
| 209 | + // use tokenBaseInner to parse the expression |
| 210 | + return tokenBaseInner(stream, state); |
213 | 211 | }
|
| 212 | + } |
| 213 | + |
| 214 | + function tokenString(stream, state) { |
214 | 215 | while (!stream.eol()) {
|
215 | 216 | stream.eatWhile(/[^'"\{\}\\]/);
|
216 | 217 | if (stream.eat("\\")) {
|
217 | 218 | stream.next();
|
218 | 219 | if (singleline && stream.eol())
|
219 | 220 | return OUTCLASS;
|
220 | 221 | } else if (stream.match(delimiter)) {
|
221 |
| - state.tokenize = tokenBase; |
| 222 | + state.tokenize = tokenOuter; |
222 | 223 | return OUTCLASS;
|
223 | 224 | } else if (stream.match('{{')) {
|
224 | 225 | // ignore {{ in f-str
|
225 | 226 | return OUTCLASS;
|
226 | 227 | } else if (stream.match('{', false)) {
|
227 | 228 | // switch to nested mode
|
228 |
| - state.fstr_state = {}; |
| 229 | + state.tokenize = tokenFString |
229 | 230 | if (stream.current()) {
|
230 | 231 | return OUTCLASS;
|
231 | 232 | } else {
|
|
246 | 247 | if (parserConf.singleLineStringErrors)
|
247 | 248 | return ERRORCLASS;
|
248 | 249 | else
|
249 |
| - state.tokenize = tokenBase; |
| 250 | + state.tokenize = tokenOuter; |
250 | 251 | }
|
251 | 252 | return OUTCLASS;
|
252 | 253 | }
|
|
358 | 359 | return {
|
359 | 360 | tokenize: tokenBase,
|
360 | 361 | scopes: [{offset: basecolumn || 0, type: "py", align: null}],
|
361 |
| - fstr_state: null, |
362 | 362 | indent: basecolumn || 0,
|
363 | 363 | lastToken: null,
|
364 | 364 | lambda: false,
|
|
0 commit comments