Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Unified Diff: client/dom/scripts/emitter.py

Issue 9845043: Rename client/{dom,html} to lib/{dom,html} . (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « client/dom/scripts/databasebuilder_test.py ('k') | client/dom/scripts/emitter_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: client/dom/scripts/emitter.py
===================================================================
--- client/dom/scripts/emitter.py (revision 5796)
+++ client/dom/scripts/emitter.py (working copy)
@@ -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)
« no previous file with comments | « client/dom/scripts/databasebuilder_test.py ('k') | client/dom/scripts/emitter_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698