| Index: sdk/lib/html/scripts/emitter.py
|
| diff --git a/sdk/lib/html/scripts/emitter.py b/sdk/lib/html/scripts/emitter.py
|
| deleted file mode 100755
|
| index 792458f540347bdbbfcf1a52a4dfe73f419783f5..0000000000000000000000000000000000000000
|
| --- a/sdk/lib/html/scripts/emitter.py
|
| +++ /dev/null
|
| @@ -1,217 +0,0 @@
|
| -#!/usr/bin/python
|
| -# Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
| -# for details. All rights reserved. Use of this source code is governed by a
|
| -# BSD-style license that can be found in the LICENSE file.
|
| -
|
| -"""Templating to help generate structured text."""
|
| -
|
| -import logging
|
| -import re
|
| -
|
| -_logger = logging.getLogger('emitter')
|
| -
|
| -
|
| -def Format(template, **parameters):
|
| - """Create a string using the same template syntax as Emitter.Emit."""
|
| - e = Emitter()
|
| - e._Emit(template, parameters)
|
| - return ''.join(e.Fragments())
|
| -
|
| -
|
| -class Emitter(object):
|
| - """An Emitter collects string fragments to be assembled into a single string.
|
| - """
|
| -
|
| - def __init__(self, bindings=None):
|
| - self._items = [] # A new list
|
| - self._bindings = bindings or Emitter.Frame({}, None)
|
| -
|
| - def EmitRaw(self, item):
|
| - """Emits literal string with no substitition."""
|
| - self._items.append(item)
|
| -
|
| - def Emit(self, template_source, **parameters):
|
| - """Emits a template, substituting named parameters and returning emitters to
|
| - fill the named holes.
|
| -
|
| - Ordinary substitution occurs at $NAME or $(NAME). If there is no parameter
|
| - called NAME, the text is left as-is. So long as you don't bind FOO as a
|
| - parameter, $FOO in the template will pass through to the generated text.
|
| -
|
| - Substitution of $?NAME and $(?NAME) yields an empty string if NAME is not a
|
| - parameter.
|
| -
|
| - Values passed as named parameters should be strings or simple integral
|
| - values (int or long).
|
| -
|
| - Named holes are created at $!NAME or $(!NAME). A hole marks a position in
|
| - the template that may be filled in later. An Emitter is returned for each
|
| - named hole in the template. The holes are filled by emitting to the
|
| - corresponding emitter.
|
| -
|
| - Emit returns either a single Emitter if the template contains one hole or a
|
| - tuple of emitters for several holes, in the order that the holes occur in
|
| - the template.
|
| -
|
| - The emitters for the holes remember the parameters passed to the initial
|
| - call to Emit. Holes can be used to provide a binding context.
|
| - """
|
| - return self._Emit(template_source, parameters)
|
| -
|
| - def _Emit(self, template_source, parameters):
|
| - """Implementation of Emit, with map in place of named parameters."""
|
| - template = self._ParseTemplate(template_source)
|
| -
|
| - parameter_bindings = self._bindings.Extend(parameters)
|
| -
|
| - hole_names = template._holes
|
| -
|
| - if hole_names:
|
| - hole_map = {}
|
| - replacements = {}
|
| - for name in hole_names:
|
| - emitter = Emitter(parameter_bindings)
|
| - replacements[name] = emitter._items
|
| - hole_map[name] = emitter
|
| - full_bindings = parameter_bindings.Extend(replacements)
|
| - else:
|
| - full_bindings = parameter_bindings
|
| -
|
| - self._ApplyTemplate(template, full_bindings)
|
| -
|
| - # Return None, a singleton or tuple of the hole names.
|
| - if not hole_names:
|
| - return None
|
| - if len(hole_names) == 1:
|
| - return hole_map[hole_names[0]]
|
| - else:
|
| - return tuple(hole_map[name] for name in hole_names)
|
| -
|
| - def Fragments(self):
|
| - """Returns a list of all the string fragments emitted."""
|
| - def _FlattenTo(item, output):
|
| - if isinstance(item, list):
|
| - for subitem in item:
|
| - _FlattenTo(subitem, output)
|
| - elif isinstance(item, Emitter.DeferredLookup):
|
| - value = item._environment.Lookup(item._lookup._name,
|
| - item._lookup._value_if_missing)
|
| - _FlattenTo(value, output)
|
| - else:
|
| - output.append(str(item))
|
| -
|
| - output = []
|
| - _FlattenTo(self._items, output)
|
| - return output
|
| -
|
| - def Bind(self, var, template_source, **parameters):
|
| - """Adds a binding for var to this emitter."""
|
| - template = self._ParseTemplate(template_source)
|
| - if template._holes:
|
| - raise RuntimeError('Cannot have holes in Emitter.Bind')
|
| - bindings = self._bindings.Extend(parameters)
|
| - value = Emitter(bindings)
|
| - value._ApplyTemplate(template, bindings)
|
| - self._bindings = self._bindings.Extend({var: value._items})
|
| - return value
|
| -
|
| - def _ParseTemplate(self, source):
|
| - """Converts the template string into a Template object."""
|
| - # TODO(sra): Cache the parsing.
|
| - items = []
|
| - holes = []
|
| -
|
| - # Break source into a sequence of text fragments and substitution lookups.
|
| - pos = 0
|
| - while True:
|
| - match = Emitter._SUBST_RE.search(source, pos)
|
| - if not match:
|
| - items.append(source[pos:])
|
| - break
|
| - text_fragment = source[pos : match.start()]
|
| - if text_fragment:
|
| - items.append(text_fragment)
|
| - pos = match.end()
|
| - term = match.group()
|
| - name = match.group(1) or match.group(2) # $NAME and $(NAME)
|
| - if name:
|
| - item = Emitter.Lookup(name, term, term)
|
| - items.append(item)
|
| - continue
|
| - name = match.group(3) or match.group(4) # $!NAME and $(!NAME)
|
| - if name:
|
| - item = Emitter.Lookup(name, term, term)
|
| - items.append(item)
|
| - holes.append(name)
|
| - continue
|
| - name = match.group(5) or match.group(6) # $?NAME and $(?NAME)
|
| - if name:
|
| - item = Emitter.Lookup(name, term, '')
|
| - items.append(item)
|
| - holes.append(name)
|
| - continue
|
| - raise RuntimeError('Unexpected group')
|
| -
|
| - if len(holes) != len(set(holes)):
|
| - raise RuntimeError('Cannot have repeated holes %s' % holes)
|
| - return Emitter.Template(items, holes)
|
| -
|
| - _SUBST_RE = re.compile(
|
| - # $FOO $(FOO) $!FOO $(!FOO) $?FOO $(?FOO)
|
| - r'\$(\w+)|\$\((\w+)\)|\$!(\w+)|\$\(!(\w+)\)|\$\?(\w+)|\$\(\?(\w+)\)')
|
| -
|
| - def _ApplyTemplate(self, template, bindings):
|
| - """Emits the items from the parsed template."""
|
| - result = []
|
| - for item in template._items:
|
| - if isinstance(item, str):
|
| - if item:
|
| - result.append(item)
|
| - elif isinstance(item, Emitter.Lookup):
|
| - # Bind lookup to the current environment (bindings)
|
| - # TODO(sra): More space efficient to do direct lookup.
|
| - result.append(Emitter.DeferredLookup(item, bindings))
|
| - else:
|
| - raise RuntimeError('Unexpected template element')
|
| - # Collected fragments are in a sublist, so self._items contains one element
|
| - # (sublist) per template application.
|
| - self._items.append(result)
|
| -
|
| - class Lookup(object):
|
| - """An element of a parsed template."""
|
| - def __init__(self, name, original, default):
|
| - self._name = name
|
| - self._original = original
|
| - self._value_if_missing = default
|
| -
|
| - class DeferredLookup(object):
|
| - """A lookup operation that is deferred until final string generation."""
|
| - # TODO(sra): A deferred lookup will be useful when we add expansions that
|
| - # have behaviour condtional on the contents, e.g. adding separators between
|
| - # a list of items.
|
| - def __init__(self, lookup, environment):
|
| - self._lookup = lookup
|
| - self._environment = environment
|
| -
|
| - class Template(object):
|
| - """A parsed template."""
|
| - def __init__(self, items, holes):
|
| - self._items = items # strings and lookups
|
| - self._holes = holes
|
| -
|
| -
|
| - class Frame(object):
|
| - """A Frame is a set of bindings derived from a parent."""
|
| - def __init__(self, map, parent):
|
| - self._map = map
|
| - self._parent = parent
|
| -
|
| - def Lookup(self, name, default):
|
| - if name in self._map:
|
| - return self._map[name]
|
| - if self._parent:
|
| - return self._parent.Lookup(name, default)
|
| - return default
|
| -
|
| - def Extend(self, map):
|
| - return Emitter.Frame(map, self)
|
|
|