170 return parsed, pos |
170 return parsed, pos |
171 else: |
171 else: |
172 raise error.ProgrammingError('unexpected type: %s' % typ) |
172 raise error.ProgrammingError('unexpected type: %s' % typ) |
173 raise error.ProgrammingError('unterminated scanning of template') |
173 raise error.ProgrammingError('unterminated scanning of template') |
174 |
174 |
|
175 def scantemplate(tmpl): |
|
176 """Scan (type, start, end) positions of outermost elements in template |
|
177 |
|
178 >>> list(scantemplate(b'foo{bar}"baz')) |
|
179 [('string', 0, 3), ('template', 3, 8), ('string', 8, 12)] |
|
180 >>> list(scantemplate(b'outer{"inner"}outer')) |
|
181 [('string', 0, 5), ('template', 5, 14), ('string', 14, 19)] |
|
182 >>> list(scantemplate(b'foo\\{escaped}')) |
|
183 [('string', 0, 5), ('string', 5, 13)] |
|
184 """ |
|
185 last = None |
|
186 for typ, val, pos in _scantemplate(tmpl, 0, len(tmpl)): |
|
187 if last: |
|
188 yield last + (pos,) |
|
189 if typ == 'end': |
|
190 return |
|
191 else: |
|
192 last = (typ, pos) |
|
193 raise error.ProgrammingError('unterminated scanning of template') |
|
194 |
175 def _scantemplate(tmpl, start, stop, quote=''): |
195 def _scantemplate(tmpl, start, stop, quote=''): |
176 """Parse template string into chunks of strings and template expressions""" |
196 """Parse template string into chunks of strings and template expressions""" |
177 sepchars = '{' + quote |
197 sepchars = '{' + quote |
178 pos = start |
198 pos = start |
179 p = parser.parser(elements) |
199 p = parser.parser(elements) |