Refactoring in the way the parse function is invoked.

--HG--
branch : trunk
diff --git a/jinja2/compiler.py b/jinja2/compiler.py
index f0deeff..5179003 100644
--- a/jinja2/compiler.py
+++ b/jinja2/compiler.py
@@ -606,7 +606,7 @@
         )
         if overriden_closure_vars:
             self.fail('It\'s not possible to set and access variables '
-                      'derived from an outer scope! (affects: %s' %
+                      'derived from an outer scope! (affects: %s)' %
                       ', '.join(sorted(overriden_closure_vars)), node.lineno)
 
         # remove variables from a closure from the frame's undeclared
diff --git a/jinja2/environment.py b/jinja2/environment.py
index 603c4aa..75f58d6 100644
--- a/jinja2/environment.py
+++ b/jinja2/environment.py
@@ -365,14 +365,18 @@
         If you are :ref:`developing Jinja2 extensions <writing-extensions>`
         this gives you a good overview of the node tree generated.
         """
-        if isinstance(filename, unicode):
-            filename = filename.encode('utf-8')
         try:
-            return Parser(self, source, name, filename).parse()
+            return self._parse(source, name, filename)
         except TemplateSyntaxError:
             exc_info = sys.exc_info()
         self.handle_exception(exc_info, source_hint=source)
 
+    def _parse(self, source, name, filename):
+        """Internal parsing function used by `parse` and `compile`."""
+        if isinstance(filename, unicode):
+            filename = filename.encode('utf-8')
+        return Parser(self, source, name, filename).parse()
+
     def lex(self, source, name=None, filename=None):
         """Lex the given sourcecode and return a generator that yields
         tokens as tuples in the form ``(lineno, token_type, value)``.
@@ -424,18 +428,24 @@
         code equivalent to the bytecode returned otherwise.  This method is
         mainly used internally.
         """
-        if isinstance(source, basestring):
-            source = self.parse(source, name, filename)
-        if self.optimized:
-            source = optimize(source, self)
-        source = generate(source, self, name, filename)
-        if raw:
-            return source
-        if filename is None:
-            filename = '<template>'
-        elif isinstance(filename, unicode):
-            filename = filename.encode('utf-8')
-        return compile(source, filename, 'exec')
+        source_hint = None
+        try:
+            if isinstance(source, basestring):
+                source_hint = source
+                source = self._parse(source, name, filename)
+            if self.optimized:
+                source = optimize(source, self)
+            source = generate(source, self, name, filename)
+            if raw:
+                return source
+            if filename is None:
+                filename = '<template>'
+            elif isinstance(filename, unicode):
+                filename = filename.encode('utf-8')
+            return compile(source, filename, 'exec')
+        except TemplateSyntaxError:
+            exc_info = sys.exc_info()
+        self.handle_exception(exc_info, source_hint=source)
 
     def compile_expression(self, source, undefined_to_none=True):
         """A handy helper method that returns a callable that accepts keyword