root/livinglogic.python.xist/src/ll/ul4c.py @ 3446:79cfc39e3bd9

Revision 3446:79cfc39e3bd9, 65.9 KB (checked in by Walter Doerwald <walter@…>, 11 years ago)

Add a FIXME comment.

Line 
1# -*- coding: utf-8 -*-
2
3## Copyright 2008 by LivingLogic AG, Bayreuth/Germany
4## Copyright 2008 by Walter Dörwald
5##
6## All Rights Reserved
7##
8## See ll/__init__.py for the license
9
10
11from __future__ import division
12
13"""
14:mod:`ll.ul4c` provides templating for XML/HTML as well as any other text-based
15format. A template defines placeholders for data output and basic logic (like
16loops and conditional blocks), that define how the final rendered output will
17look.
18
19:mod:`ll.ul4c` compiles a template to a bytecode format, which makes it possible
20to implement renderers for these templates in multiple programming languages.
21"""
22
23__docformat__ = "reStructuredText"
24
25
26import re, datetime, marshal, StringIO, locale
27
28from ll import spark
29
30
31# Regular expression used for splitting dates
32datesplitter = re.compile("[-T:.]")
33
34
35###
36### Location information
37###
38
39class Location(object):
40    """
41    A :class:`Location` object contains information about the location of a
42    template tag.
43    """
44    __slots__ = ("source", "type", "starttag", "endtag", "startcode", "endcode")
45
46    def __init__(self, source, type, starttag, endtag, startcode, endcode):
47        """
48        Create a new :class:`Location` object. The arguments have the following
49        meaning:
50
51        :var:`source`
52            The complete source string
53
54        :var:`type`
55            The tag type (i.e. ``"for"``, ``"if"``, etc.)
56
57        :var:`starttag`
58            The start position of the start delimiter.
59
60        :var:`endtag`
61            The end position of the end delimiter.
62
63        :var:`startcode`
64            The start position of the tag code.
65
66        :var:`endcode`
67            The end position of the tag code.
68        """
69        self.source = source
70        self.type = type
71        self.starttag = starttag
72        self.endtag = endtag
73        self.startcode = startcode
74        self.endcode = endcode
75
76    @property
77    def code(self):
78        return self.source[self.startcode:self.endcode]
79
80    @property
81    def tag(self):
82        return self.source[self.starttag:self.endtag]
83
84    def __str__(self):
85        lastlinefeed = self.source.rfind("\n", 0, self.starttag)
86        if lastlinefeed >= 0:
87            line = self.source.count("\n", 0, self.starttag)+1
88            col = self.starttag - lastlinefeed
89        else:
90            line = 1
91            col = self.starttag + 1
92        return "%r at %d (line %d, col %d)" % (self.tag, self.starttag+1, line, col)
93
94
95###
96### Exceptions
97###
98
99class Error(Exception):
100    """
101    base class of all exceptions.
102    """
103    def __init__(self, exception=None):
104        self.location = None
105        self.exception = exception
106
107    def __str__(self):
108        return self.format(str(self.exception) if self.exception is not None else "error")
109
110    def decorate(self, location):
111        self.location = location
112        return self
113
114    def format(self, message):
115        if self.exception is not None:
116            name = self.exception.__class__.__name__
117            module = self.exception.__class__.__module__
118            if module != "exceptions":
119                name = "%s.%s" % (module, name)
120            if self.location is not None:
121                return "%s in %s: %s" % (name, self.location, message)
122            else:
123                return "%s: %s" % (name, message)
124        else:
125            if self.location is not None:
126                return "in %s: %s" % (self.location, message)
127            else:
128                return message
129
130
131class LexicalError(Error):
132    def __init__(self, start, end, input):
133        Error.__init__(self)
134        self.start = start
135        self.end = end
136        self.input = input
137
138    def __str__(self):
139        return self.format("Unmatched input %r" % self.input)
140
141
142class SyntaxError(Error):
143    def __init__(self, token):
144        Error.__init__(self)
145        self.token = token
146
147    def __str__(self):
148        return self.format("Lexical error near %r" % str(self.token))
149
150
151class UnterminatedStringError(Error):
152    """
153    Exception that is raised by the parser when a string constant is not
154    terminated.
155    """
156    def __str__(self):
157        return self.format("Unterminated string")
158
159
160class BlockError(Error):
161    """
162    Exception that is raised by the compiler when an illegal block structure is
163    detected (e.g. an ``endif`` without a previous ``if``).
164    """
165
166    def __init__(self, message):
167        Error.__init__(self)
168        self.message = message
169
170    def __str__(self):
171        return self.format(self.message)
172
173
174class UnknownFunctionError(Error):
175    """
176    Exception that is raised by the renderer if the function to be executed by
177    the ``callfunc0``, ``callfunc1``, ``callfunc2`` or ``callfunc3`` opcodes is
178    unknown.
179    """
180
181    def __init__(self, funcname):
182        Error.__init__(self)
183        self.funcname = funcname
184
185    def __str__(self):
186        return self.format("function %r unknown" % self.funcname)
187
188
189class UnknownMethodError(Error):
190    """
191    Exception that is raised by the renderer if the method to be executed by the
192    ``callmeth0``, ``callmeth1``, ``callmeth2``  or ``callmeth3`` opcodes is
193    unknown.
194    """
195
196    def __init__(self, methname):
197        Error.__init__(self)
198        self.methname = methname
199
200    def __str__(self):
201        return self.format("method %r unknown" % self.methname)
202
203
204class UnknownOpcodeError(Error):
205    """
206    Exception that is raised when an unknown opcode is encountered by the renderer.
207    """
208
209    def __init__(self, opcode):
210        Error.__init__(self)
211        self.opcode = opcode
212
213    def __str__(self):
214        return self.format("opcode %r unknown" % self.opcode)
215
216
217class OutOfRegistersError(Error):
218    """
219    Exception that is raised by the compiler when there are no more free
220    registers. This might happen with very complex expressions in tag code.
221    """
222
223    def __str__(self):
224        return self.format("out of registers")
225
226
227###
228### opcode class
229###
230
231class Opcode(object):
232    """
233    An :class:`Opcode` stores an opcode. The type of opcode is stored in the
234    :attr:`code` attribute. Furthermore each opcode has up to five register
235    specifications (for the source or targets of the operation) in the attributes
236    :attr:`r1`, :attr:`r2`, :attr:`r3`, :attr:`r4` and :attr:`r5`. If the opcode
237    requires an additional argument (like a variable name or the value of a
238    constant) this will be stored in the :attr:`arg` attribute.
239
240    The following opcodes are available:
241
242    :const:`None`:
243        Print text. The text is available from ``location.code``.
244
245    ``"print"``:
246        Print the content of register :attr:`r1`. (If the object in the register
247        is not a string, it will be converted to a string first.)
248
249    ``"loadnone"``:
250        Load the constant :const:`None`.
251
252    ``"loadfalse"``:
253        Load the constant :const:`False`.
254
255    ``"loadtrue"``:
256        Load the constant :const:`True`.
257
258    ``"loadstr"``:
259        Load the string :attr:`arg` into the register :attr:`r1`.
260
261    ``"loadint"``:
262        Load the integer value :attr:`arg` into the register :attr:`r1`.
263
264    ``"loadfloat"``:
265        Load the float value :attr:`arg` into the register :attr:`r1`.
266
267    ``"loaddate"``:
268        Load the date value :attr:`arg` into the register :attr:`r1`. :attr:`arg`
269        must be in ISO format (e.g. ``2008-07-02T11:05:55.460464``).
270
271    ``"buildlist"``:
272        Load an empty list into the register :attr:`r1`.
273
274    ``"builddict"``:
275        Load an empty dictionary into the register :attr:`r1`.
276
277    ``"addlist"``
278        Append the object in register :attr:`r2` to the list in register :attr:`r1`.
279   
280    ``"adddict"``
281        Add a new entry to the dictionary in register :attr:`r1`. The object in
282        :attr:`r2` is the key and the object in register :attr:`r3` is the value.
283   
284    ``"loadvar"``:
285        Load the variable named :attr:`arg` into the register :attr:`r1`.
286
287    ``"storevar"``:
288        Store the content of register :attr:`r1` in the variable named :attr:`arg`.
289
290    ``"addvar"``:
291        Add the content of register :attr:`r1` to the variable named :attr:`arg`.
292
293    ``"for"``:
294        Start a loop over the object in the register :attr:`r2` and store the
295        object from each loop iteration in the register :attr:`r1`.
296
297    ``"endfor"``:
298        Ends the innermost running ``for`` loop.
299
300    ``"if"``:
301        Starts a conditional block. If the objects in the register :attr:`r1` is
302        true the block will be executed. The "block" consists of all opcodes after
303        the ``if`` upto the matching ``else`` or ``endif`` opcode.
304
305    ``"else"``:
306        Start the else branch of the previous ``if``.
307
308    ``"endif"``:
309        End a conditional block.
310
311    ``"getattr"``:
312        Get the attribute named :attr:`arg` from the object in register :attr:`r2`
313        and store it in register :attr:`r1`.
314
315    ``"getitem"``:
316        Get an item from the object in register :attr:`r2`. If this object is a
317        list the object in register :attr:`r3` will be used as the index. If it is
318        a dictionary :attr:`r3` will be used as the key. The result will be stored
319        in register :attr:`r1`.
320
321    ``"getslice12"``:
322        Get an slice from the object in register :attr:`r2`. The object in
323        register :attr:`r3` (which must be an ``int`` or :const:`None`) specifies
324        the start index, If this object in register :attr:`r4` specifies the end
325        index. The result will be stored in register :attr:`r1`.
326
327    ``"getslice1"``:
328        Similar to ``getslice12`` except that the end index is always the length
329        of the object.
330
331    ``"getslice2"``:
332        Similar to ``getslice12`` except that the start index is always 0 and the
333        end index is in register :attr:`r3`.
334
335    ``"getslice"``:
336        Similar to ``getslice12`` except that the start index is always 0 and the
337        end index alywas the length of the object.
338
339    ``"not"``:
340        Invert the truth value of the object in register :attr:`r2` and stores the
341        resulting bool in the register :attr:`r1`.
342
343    ``"equals"``:
344        Compare the objects in register :attr:`r2` and :attr:`r3` and store
345        ``True`` in the register :attr:`r1` if they are equal, ``False`` otherwise.
346
347    ``"notequals"``:
348        Compare the objects in register :attr:`r2` and :attr:`r3` and store
349        ``False`` in the register :attr:`r1` if they are equal, ``True`` otherwise.
350
351    ``"contains"``:
352        Test whether the object in register :attr:`r3` contains the object in
353        register :attr:`r2` (either as a key if it's a dictionary or as an item
354        if it's a list or as a substring if it's a string) and store ``True`` into
355        the register :attr:`r1` if it does, ``False`` otherwise.
356
357    ``"notcontains"``:
358        Test whether the object in register :attr:`r3` contains the object in
359        register :attr:`r2` (either as a key if it's a dictionary or as an item
360        if it's a list or as a substring if it's a string) and store ``False`` into
361        the register :attr:`r1` if it does, ``True`` otherwise.
362
363    ``"or"``:
364        Check the truth value of two object in registers :attr:`r2` and :attr:`r3`
365        and store :attr:`r2` in the register :attr:`r1` if it is true, :attr:`r3`
366        otherwise).
367
368    ``"and"``:
369        Check the truth value of two object in registers :attr:`r2` and :attr:`r3`
370        and store :attr:`r3` in the register :attr:`r1` if :attr:`r2` is true,
371        :attr:`r3` otherwise).
372
373    ``"mod"``:
374        Does a modulo operation: Calculates :attr:`r2` modulo :attr:`r3` and stores
375        the result in the register :attr:`r1`.
376
377    ``"callfunc0"``:
378        Call the function named :attr:`arg` without any arguments and store the
379        return value in register :attr:`r1`.
380
381    ``"callfunc1"``:
382        Call the function named :attr:`arg` with the content of register :attr:`r2`
383        as an argument and store the return value in register :attr:`r1`.
384
385    ``"callfunc2"``:
386        Call the function named :attr:`arg` with the contents of register
387        :attr:`r2` and :attr:`r3` as the two arguments and store the return value
388        in register :attr:`r1`.
389
390    ``"callfunc3"``:
391        Call the function named :attr:`arg` with the contents of register
392        :attr:`r2`, :attr:`r3` and :attr:`r4` as the three arguments and store
393        the return value in register :attr:`r1`.
394
395    ``"callmeth0"``:
396        Call the method named :attr:`arg` on the object in register :attr:`r2`
397        and store the return value in register :attr:`r1`.
398
399    ``"callmeth1"``:
400        Call the method named :attr:`arg` on the object in register :attr:`r2`
401        using the object in register :attr:`r3` as to only argument and store the
402        return value in register :attr:`r1`.
403
404    ``"callmeth2"``:
405        Call the method named :attr:`arg` on the object in register :attr:`r2`
406        using the objects in register :attr:`r3` and :attr:`r4` as arguments and
407        store the return value in register :attr:`r1`.
408
409    ``"callmeth3"``:
410        Call the method named :attr:`arg` on the object in register :attr:`r2`
411        using the objects in register :attr:`r3`, :attr:`r4` and :attr:`r5` as
412        arguments and store the return value in register :attr:`r1`.
413
414    ``"render"``:
415        Render the template whose name is in the attribute :attr:`arg`. The
416        content of register :attr:`r1` will be passed as the data object to the
417        template.
418    """
419    __slots__ = ("code", "r1", "r2", "r3", "r4", "r5", "arg", "location", "jump")
420
421    def __init__(self, code, r1=None, r2=None, r3=None, r4=None, r5=None, arg=None, location=None):
422        self.code = code
423        self.r1 = r1
424        self.r2 = r2
425        self.r3 = r3
426        self.r4 = r4
427        self.r5 = r5
428        self.arg = arg
429        self.location = location
430        self.jump = None
431
432    def __repr__(self):
433        v = ["<", self.__class__.__name__, " code=%r" % self.code]
434        for attrname in ("r1", "r2", "r3", "r4", "r5", "arg"):
435            attr = getattr(self, attrname)
436            if attr is not None:
437                v.append(" %s=%r" % (attrname, attr))
438        if self.code is None:
439            v.append(" text=%r" % self.location.code)
440        v.append(" at 0x%x>" % id(self))
441        return "".join(v)
442
443    def __str__(self):
444        if self.code is None:
445            return "print %r" % self.location.code
446        elif self.code == "print":
447            return "print r%r" % self.r1
448        elif self.code == "loadnone":
449            return "r%r = None" % self.r1
450        elif self.code == "loadfalse":
451            return "r%r = False" % self.r1
452        elif self.code == "loadtrue":
453            return "r%r = True" % self.r1
454        elif self.code == "loadstr":
455            return "r%r = %r" % (self.r1, self.arg)
456        elif self.code == "loadint":
457            return "r%r = %s" % (self.r1, self.arg)
458        elif self.code == "loadfloat":
459            return "r%r = %s" % (self.r1, self.arg)
460        elif self.code == "loaddate":
461            return "r%r = %s" % (self.r1, self.arg)
462        elif self.code == "buildlist":
463            return "r%r = []" % (self.r1)
464        elif self.code == "builddict":
465            return "r%r = {}" % (self.r1)
466        elif self.code == "addlist":
467            return "r%r.append(r%r)" % (self.r1, self.r2)
468        elif self.code == "adddict":
469            return "r%r[r%r] = r%r" % (self.r1, self.r2, self.r3)
470        elif self.code == "loadvar":
471            return "r%r = vars[%r]" % (self.r1, self.arg)
472        elif self.code == "storevar":
473            return "vars[%r] = r%r" % (self.arg, self.r1)
474        elif self.code == "addvar":
475            return "vars[%r] += r%r" % (self.arg, self.r1)
476        elif self.code == "subvar":
477            return "vars[%r] -= r%r" % (self.arg, self.r1)
478        elif self.code == "mulvar":
479            return "vars[%r] *= r%r" % (self.arg, self.r1)
480        elif self.code == "truedivvar":
481            return "vars[%r] /= r%r" % (self.arg, self.r1)
482        elif self.code == "floordivvar":
483            return "vars[%r] //= r%r" % (self.arg, self.r1)
484        elif self.code == "modvar":
485            return "vars[%r] %%= r%r" % (self.arg, self.r1)
486        elif self.code == "delvar":
487            return "del vars[%r]" % self.arg
488        elif self.code == "for":
489            return "for r%r in r%r" % (self.r1, self.r2)
490        elif self.code == "endfor":
491            return "endfor"
492        elif self.code == "if":
493            return "if r%r" % self.r1
494        elif self.code == "else":
495            return "else"
496        elif self.code == "endif":
497            return "endif"
498        elif self.code == "getattr":
499            return "r%r = getattr(r%r, %r)" % (self.r1, self.r2, self.arg)
500        elif self.code == "getitem":
501            return "r%r = r%r[r%r]" % (self.r1, self.r2, self.r3)
502        elif self.code == "getslice":
503            return "r%r = r%r[:]" % (self.r1, self.r2)
504        elif self.code == "getslice1":
505            return "r%r = r%r[r%r:]" % (self.r1, self.r2, self.r3)
506        elif self.code == "getslice2":
507            return "r%r = r%r[:r%r]" % (self.r1, self.r2, self.r4)
508        elif self.code == "getslice12":
509            return "r%r = r%r[r%r:r%r]" % (self.r1, self.r2, self.r3, self.r4)
510        elif self.code == "not":
511            return "r%r = not r%r" % (self.r1, self.r2)
512        elif self.code == "equals":
513            return "r%r = r%r == r%r" % (self.r1, self.r2, self.r3)
514        elif self.code == "notequals":
515            return "r%r = r%r != r%r" % (self.r1, self.r2, self.r3)
516        elif self.code == "contains":
517            return "r%r = r%r in r%r" % (self.r1, self.r2, self.r3)
518        elif self.code == "notcontains":
519            return "r%r = r%r not in r%r" % (self.r1, self.r2, self.r3)
520        elif self.code == "add":
521            return "r%r = r%r + r%r" % (self.r1, self.r2, self.r3)
522        elif self.code == "sub":
523            return "r%r = r%r - r%r" % (self.r1, self.r2, self.r3)
524        elif self.code == "mul":
525            return "r%r = r%r * r%r" % (self.r1, self.r2, self.r3)
526        elif self.code == "floordiv":
527            return "r%r = r%r // r%r" % (self.r1, self.r2, self.r3)
528        elif self.code == "trueiv":
529            return "r%r = r%r / r%r" % (self.r1, self.r2, self.r3)
530        elif self.code == "and":
531            return "r%r = r%r and r%r" % (self.r1, self.r2, self.r3)
532        elif self.code == "or":
533            return "r%r = r%r or r%r" % (self.r1, self.r2, self.r3)
534        elif self.code == "mod":
535            return "r%r = r%r %% r%r" % (self.r1, self.r2, self.r3)
536        elif self.code == "callfunc0":
537            return "r%r = %s()" % (self.r1, self.arg)
538        elif self.code == "callfunc1":
539            return "r%r = %s(r%r)" % (self.r1, self.arg, self.r2)
540        elif self.code == "callfunc2":
541            return "r%r = %s(r%r, r%r)" % (self.r1, self.arg, self.r2, self.r3)
542        elif self.code == "callfunc3":
543            return "r%r = %s(r%r, r%r, r%r)" % (self.r1, self.arg, self.r2, self.r3, self.r4)
544        elif self.code == "callmeth0":
545            return "r%r = r%r.%s()" % (self.r1, self.r2, self.arg)
546        elif self.code == "callmeth1":
547            return "r%r = r%r.%s(r%r)" % (self.r1, self.r2, self.arg, self.r3)
548        elif self.code == "callmeth2":
549            return "r%r = r%r.%s(r%r, r%r)" % (self.r1, self.r2, self.arg, self.r3, self.r4)
550        elif self.code == "callmeth3":
551            return "r%r = r%r.%s(r%r, r%r, r%r)" % (self.r1, self.r2, self.arg, self.r3, self.r4, self.r5)
552        elif self.code == "render":
553            return "render %s(r%r)" % (self.arg, self.r1)
554        else:
555            raise UnknownOpcodeError(self.code)
556
557
558class Template(object):
559    def __init__(self):
560        self.startdelim = None
561        self.enddelim = None
562        self.source = None
563        self.opcodes = None
564        # The following is used for converting the opcodes back to executable Python code
565        self._pythonfunction = None
566
567    @classmethod
568    def loads(cls, data):
569        def _readint(term):
570            i = 0
571            while True:
572                c = stream.read(1)
573                if c.isdigit():
574                    i = 10*i+int(c)
575                elif c == term:
576                    return i
577                else:
578                    raise ValueError("invalid terminator, expected %r, got %r" % (term, c))
579
580        def _readstr(term1, term0):
581            i = 0
582            while True:
583                c = stream.read(1)
584                if c.isdigit():
585                    i = 10*i+int(c)
586                elif c == term1:
587                    break
588                elif c == term0:
589                    return None
590                else:
591                    raise ValueError("invalid terminator, expected %r or %r, got %r" % (term1, term0, c))
592            s = stream.read(i)
593            if len(s) != i:
594                raise ValueError("short read")
595            return s
596
597        def _readspec():
598            c = stream.read(1)
599            if c == "-":
600                return None
601            elif c.isdigit():
602                return int(c)
603            else:
604                raise ValueError("invalid register spec %r" % c)
605
606        def _readcr():
607            c = stream.read(1)
608            if c != "\n":
609                raise ValueError("invalid linefeed %r" % c)
610
611        self = cls()
612        stream = StringIO.StringIO(data)
613        header = stream.readline()
614        header = header.rstrip()
615        if header != "ul4":
616            raise ValueError("invalid header, expected 'ul4', got %r" % header)
617        version = stream.readline()
618        version = version.rstrip()
619        if version != "1":
620            raise ValueError("invalid version, expected 1 got, %r" % version)
621        self.startdelim = _readstr(u"<", u"[")
622        _readcr()
623        self.enddelim = _readstr(u">", u"]")
624        _readcr()
625        self.source = _readstr("'", '"')
626        self.opcodes = []
627        _readcr()
628        count = _readint(u"#")
629        _readcr()
630        location = None
631        while count:
632            r1 = _readspec()
633            r2 = _readspec()
634            r3 = _readspec()
635            r4 = _readspec()
636            r5 = _readspec()
637            code = _readstr(":", ".")
638            arg = _readstr(";", ",")
639            locspec = stream.read(1)
640            if locspec == u"^":
641                if location is None:
642                    raise ValueError("no previous location")
643            elif locspec == u"*":
644                location = Location(self.source, _readstr("=", "-"), _readint("("), _readint(")"), _readint("{"), _readint("}"))
645            else:
646                raise ValueError("invalid location spec %r" % locspec)
647            _readcr()
648            count -= 1
649            self.opcodes.append(Opcode(code, r1, r2, r3, r4, r5, arg, location))
650        return self
651
652    @classmethod
653    def load(cls, stream):
654        return cls.loads(stream.read())
655
656    def iterdump(self):
657        def _writeint(term, number):
658            yield unicode(number)
659            yield term
660
661        def _writestr(term1, term0, string):
662            if string:
663                yield str(len(string))
664            if string is None:
665                yield term0
666            else:
667                yield term1
668                yield string
669
670        yield "ul4\n1\n"
671        for p in _writestr("<", "[", self.startdelim): yield p
672        yield "\n"
673        for p in _writestr(">", "]", self.enddelim): yield p
674        yield "\n"
675        for p in _writestr("'", '"', self.source): yield p
676        yield "\n"
677        for p in _writeint("#", len(self.opcodes)): yield p
678        yield "\n"
679        lastlocation = None
680        for opcode in self.opcodes:
681            yield str(opcode.r1) if opcode.r1 is not None else u"-"
682            yield str(opcode.r2) if opcode.r2 is not None else u"-"
683            yield str(opcode.r3) if opcode.r3 is not None else u"-"
684            yield str(opcode.r4) if opcode.r4 is not None else u"-"
685            yield str(opcode.r5) if opcode.r5 is not None else u"-"
686            for p in _writestr(":", ".", opcode.code): yield p
687            for p in _writestr(";", ",", opcode.arg): yield p
688            if opcode.location is not lastlocation:
689                lastlocation = opcode.location
690                yield u"*"
691                for p in _writestr("=", "-", lastlocation.type): yield p
692                for p in _writeint("(", lastlocation.starttag): yield p
693                for p in _writeint(")", lastlocation.endtag): yield p
694                for p in _writeint("{", lastlocation.startcode): yield p
695                for p in _writeint("}", lastlocation.endcode): yield p
696            else:
697                yield "^"
698            yield "\n"
699
700    def dump(self, stream):
701        for part in self.iterdump():
702            stream.write(part)
703
704    def dumps(self):
705        return ''.join(self.iterdump())
706
707    def pythonsource(self, function=None):
708        indent = 0
709        output = []
710
711        def _code(code):
712            output.append("%s%s" % ("\t"*indent, code))
713
714        if function is not None:
715            _code("def %s(templates={}, **variables):" % function)
716            indent += 1
717        _code("import sys, marshal, datetime")
718        _code("from ll.misc import xmlescape")
719        _code("from ll import ul4c")
720        _code("source = %r" % self.source)
721        _code('variables = dict((key.decode("utf-8"), value) for (key, value) in variables.iteritems())') # FIXME: This can be dropped in Python 3.0 where strings are unicode
722        locations = tuple((oc.location.type, oc.location.starttag, oc.location.endtag, oc.location.startcode, oc.location.endcode) for oc in self.opcodes)
723        locations = marshal.dumps(locations)
724        _code("locations = marshal.loads(%r)" % locations)
725        _code("".join("reg%d = " % i for i in xrange(10)) + "None")
726
727        _code("try:")
728        indent += 1
729        _code("startline = sys._getframe().f_lineno+1") # The source line of the first opcode
730        try:
731            lastopcode = None
732            for opcode in self.opcodes:
733                # The following code ensures that each opcode outputs exactly one source code line
734                # This makes it possible in case of an error to find out which opcode produced the error
735                if opcode.code is None:
736                    _code("yield %r" % opcode.location.code)
737                elif opcode.code == "loadstr":
738                    _code("reg%d = %r" % (opcode.r1, opcode.arg))
739                elif opcode.code == "loadint":
740                    _code("reg%d = %s" % (opcode.r1, opcode.arg))
741                elif opcode.code == "loadfloat":
742                    _code("reg%d = %s" % (opcode.r1, opcode.arg))
743                elif opcode.code == "loadnone":
744                    _code("reg%d = None" % opcode.r1)
745                elif opcode.code == "loadfalse":
746                    _code("reg%d = False" % opcode.r1)
747                elif opcode.code == "loadtrue":
748                    _code("reg%d = True" % opcode.r1)
749                elif opcode.code == "loaddate":
750                    _code("reg%d = datetime.datetime(%s)" % (opcode.r1, ", ".join(str(int(p)) for p in datesplitter.split(opcode.arg))))
751                elif opcode.code == "buildlist":
752                    _code("reg%d = []" % opcode.r1)
753                elif opcode.code == "builddict":
754                    _code("reg%d = {}" % opcode.r1)
755                elif opcode.code == "addlist":
756                    _code("reg%d.append(reg%d)" % (opcode.r1, opcode.r2))
757                elif opcode.code == "adddict":
758                    _code("reg%d[reg%d] = reg%d" % (opcode.r1, opcode.r2, opcode.r3))
759                elif opcode.code == "loadvar":
760                    _code("reg%d = variables[%r]" % (opcode.r1, opcode.arg))
761                elif opcode.code == "storevar":
762                    _code("variables[%r] = reg%d" % (opcode.arg, opcode.r1))
763                elif opcode.code == "addvar":
764                    _code("variables[%r] += reg%d" % (opcode.arg, opcode.r1))
765                elif opcode.code == "subvar":
766                    _code("variables[%r] -= reg%d" % (opcode.arg, opcode.r1))
767                elif opcode.code == "mulvar":
768                    _code("variables[%r] *= reg%d" % (opcode.arg, opcode.r1))
769                elif opcode.code == "truedivvar":
770                    _code("variables[%r] /= reg%d" % (opcode.arg, opcode.r1))
771                elif opcode.code == "floordivvar":
772                    _code("variables[%r] //= reg%d" % (opcode.arg, opcode.r1))
773                elif opcode.code == "modvar":
774                    _code("variables[%r] %%= reg%d" % (opcode.arg, opcode.r1))
775                elif opcode.code == "delvar":
776                    _code("del variables[%r]" % opcode.arg)
777                elif opcode.code == "getattr":
778                    _code("reg%d = reg%d[%r]" % (opcode.r1, opcode.r2, opcode.arg))
779                elif opcode.code == "getitem":
780                    _code("reg%d = reg%d[reg%d]" % (opcode.r1, opcode.r2, opcode.r3))
781                elif opcode.code == "getslice12":
782                    _code("reg%d = reg%d[reg%d:reg%d]" % (opcode.r1, opcode.r2, opcode.r3, opcode.r4))
783                elif opcode.code == "getslice1":
784                    _code("reg%d = reg%d[reg%d:]" % (opcode.r1, opcode.r2, opcode.r3))
785                elif opcode.code == "getslice2":
786                    _code("reg%d = reg%d[:reg%d]" % (opcode.r1, opcode.r2, opcode.r3))
787                elif opcode.code == "getslice":
788                    _code("reg%d = reg%d[:]" % (opcode.r1, opcode.r2))
789                elif opcode.code == "print":
790                    _code("if reg%d is not None: yield unicode(reg%d)" % (opcode.r1, opcode.r1))
791                elif opcode.code == "for":
792                    _code("for reg%d in reg%d:" % (opcode.r1, opcode.r2))
793                    indent += 1
794                elif opcode.code == "endfor":
795                    # we don't have to check for empty loops here, as a ``<?for?>`` tag always generates at least one ``storevar`` opcode inside the loop
796                    indent -= 1
797                    _code("# end for")
798                elif opcode.code == "not":
799                    _code("reg%d = not reg%d" % (opcode.r1, opcode.r2))
800                elif opcode.code == "neg":
801                    _code("reg%d = -reg%d" % (opcode.r1, opcode.r2))
802                elif opcode.code == "contains":
803                    _code("reg%d = reg%d in reg%d" % (opcode.r1, opcode.r2, opcode.r3))
804                elif opcode.code == "notcontains":
805                    _code("reg%d = reg%d not in reg%d" % (opcode.r1, opcode.r2, opcode.r3))
806                elif opcode.code == "equals":
807                    _code("reg%d = reg%d == reg%d" % (opcode.r1, opcode.r2, opcode.r3))
808                elif opcode.code == "notequals":
809                    _code("reg%d = reg%d != reg%d" % (opcode.r1, opcode.r2, opcode.r3))
810                elif opcode.code == "add":
811                    _code("reg%d = reg%d + reg%d" % (opcode.r1, opcode.r2, opcode.r3))
812                elif opcode.code == "sub":
813                    _code("reg%d = reg%d - reg%d" % (opcode.r1, opcode.r2, opcode.r3))
814                elif opcode.code == "mul":
815                    _code("reg%d = reg%d * reg%d" % (opcode.r1, opcode.r2, opcode.r3))
816                elif opcode.code == "floordiv":
817                    _code("reg%d = reg%d // reg%d" % (opcode.r1, opcode.r2, opcode.r3))
818                elif opcode.code == "truediv":
819                    _code("reg%d = reg%d / reg%d" % (opcode.r1, opcode.r2, opcode.r3))
820                elif opcode.code == "and":
821                    _code("reg%d = reg%d and reg%d" % (opcode.r1, opcode.r2, opcode.r3))
822                elif opcode.code == "or":
823                    _code("reg%d = reg%d or reg%d" % (opcode.r1, opcode.r2, opcode.r3))
824                elif opcode.code == "mod":
825                    _code("reg%d = reg%d %% reg%d" % (opcode.r1, opcode.r2, opcode.r3))
826                elif opcode.code == "callfunc0":
827                    if opcode.arg == "now":
828                        _code("reg%d = datetime.datetime.now()" % (opcode.r1))
829                    else:
830                        raise UnknownFunctionError(opcode.arg)
831                elif opcode.code == "callfunc1":
832                    if opcode.arg == "xmlescape":
833                        _code("reg%d = xmlescape(unicode(reg%d)) if reg%d is not None else u''" % (opcode.r1, opcode.r2, opcode.r2))
834                    elif opcode.arg == "str":
835                        _code("reg%d = unicode(reg%d) if reg%d is not None else u''" % (opcode.r1, opcode.r2, opcode.r2))
836                    elif opcode.arg == "int":
837                        _code("reg%d = int(reg%d)" % (opcode.r1, opcode.r2))
838                    elif opcode.arg == "bool":
839                        _code("reg%d = bool(reg%d)" % (opcode.r1, opcode.r2))
840                    elif opcode.arg == "len":
841                        _code("reg%d = len(reg%d)" % (opcode.r1, opcode.r2))
842                    elif opcode.arg == "enumerate":
843                        _code("reg%d = enumerate(reg%d)" % (opcode.r1, opcode.r2))
844                    elif opcode.arg == "isnone":
845                        _code("reg%d = reg%d is None" % (opcode.r1, opcode.r2))
846                    elif opcode.arg == "isstr":
847                        _code("reg%d = isinstance(reg%d, basestring)" % (opcode.r1, opcode.r2))
848                    elif opcode.arg == "isint":
849                        _code("reg%d = isinstance(reg%d, (int, long)) and not isinstance(reg%d, bool)" % (opcode.r1, opcode.r2, opcode.r2))
850                    elif opcode.arg == "isfloat":
851                        _code("reg%d = isinstance(reg%d, float)" % (opcode.r1, opcode.r2))
852                    elif opcode.arg == "isbool":
853                        _code("reg%d = isinstance(reg%d, bool)" % (opcode.r1, opcode.r2))
854                    elif opcode.arg == "isdate":
855                        _code("reg%d = isinstance(reg%d, datetime.datetime)" % (opcode.r1, opcode.r2))
856                    elif opcode.arg == "islist":
857                        _code("reg%d = isinstance(reg%d, (list, tuple))" % (opcode.r1, opcode.r2))
858                    elif opcode.arg == "isdict":
859                        _code("reg%d = isinstance(reg%d, dict)" % (opcode.r1, opcode.r2))
860                    elif opcode.arg == "repr":
861                        _code("reg%d = ul4c._repr(reg%d)" % (opcode.r1, opcode.r2))
862                    elif opcode.arg == "chr":
863                        _code("reg%d = unichr(reg%d)" % (opcode.r1, opcode.r2))
864                    elif opcode.arg == "ord":
865                        _code("reg%d = ord(reg%d)" % (opcode.r1, opcode.r2))
866                    elif opcode.arg == "hex":
867                        _code("reg%d = hex(reg%d)" % (opcode.r1, opcode.r2))
868                    elif opcode.arg == "oct":
869                        _code('reg%d = ul4c._oct(reg%d)' % (opcode.r1, opcode.r2))
870                    elif opcode.arg == "bin":
871                        _code('reg%d = ul4c._bin(reg%d)' % (opcode.r1, opcode.r2))
872                    elif opcode.arg == "sorted":
873                        _code("reg%d = sorted(reg%d)" % (opcode.r1, opcode.r2))
874                    elif opcode.arg == "range":
875                        _code("reg%d = xrange(reg%d)" % (opcode.r1, opcode.r2))
876                    else:
877                        raise UnknownFunctionError(opcode.arg)
878                elif opcode.code == "callfunc2":
879                    if opcode.arg == "range":
880                        _code("reg%d = xrange(reg%d, reg%d)" % (opcode.r1, opcode.r2, opcode.r3))
881                    else:
882                        raise UnknownFunctionError(opcode.arg)
883                elif opcode.code == "callfunc3":
884                    if opcode.arg == "range":
885                        _code("reg%d = xrange(reg%d, reg%d, reg%d)" % (opcode.r1, opcode.r2, opcode.r3, opcode.r4))
886                    else:
887                        raise UnknownFunctionError(opcode.arg)
888                elif opcode.code == "callmeth0":
889                    if opcode.arg in ("split", "rsplit", "strip", "lstrip", "rstrip", "upper", "lower", "isoformat"):
890                        _code("reg%d = reg%d.%s()" % (opcode.r1, opcode.r2, opcode.arg))
891                    elif opcode.arg == "items":
892                        _code("reg%d = reg%d.iteritems()" % (opcode.r1, opcode.r2))
893                    else:
894                        raise UnknownMethodError(opcode.arg)
895                elif opcode.code == "callmeth1":
896                    if opcode.arg in ("split", "rsplit", "strip", "lstrip", "rstrip", "startswith", "endswith", "find"):
897                        _code("reg%d = reg%d.%s(reg%d)" % (opcode.r1, opcode.r2, opcode.arg, opcode.r3))
898                    elif opcode.arg == "format":
899                        _code("reg%d = ul4c._format(reg%d, reg%d)" % (opcode.r1, opcode.r2, opcode.r3))
900                    else:
901                        raise UnknownMethodError(opcode.arg)
902                elif opcode.code == "callmeth2":
903                    if opcode.arg in ("split", "rsplit", "find"):
904                        _code("reg%d = reg%d.%s(reg%d, reg%d)" % (opcode.r1, opcode.r2, opcode.arg, opcode.r3, opcode.r4))
905                    else:
906                        raise UnknownMethodError(opcode.arg)
907                elif opcode.code == "callmeth3":
908                    if opcode.arg == "find":
909                        _code("reg%d = reg%d.%s(reg%d, reg%d, reg%d)" % (opcode.r1, opcode.r2, opcode.arg, opcode.r3, opcode.r4, opcode.r5))
910                    else:
911                        raise UnknownMethodError(opcode.arg)
912                elif opcode.code == "if":
913                    _code("if reg%d:" % opcode.r1)
914                    indent += 1
915                elif opcode.code == "else":
916                    if lastopcode == "if":
917                        output[-1] += " pass"
918                    indent -= 1
919                    _code("else:")
920                    indent += 1
921                elif opcode.code == "endif":
922                    if lastopcode in ("if", "else"):
923                        output[-1] += " pass"
924                    indent -= 1
925                    _code("# end if")
926                elif opcode.code == "render":
927                    _code('for chunk in templates[%r](templates, **dict((key.encode("utf-8"), value) for (key, value) in reg%d.iteritems())): yield chunk' % (opcode.arg, opcode.r1))
928                else:
929                    raise UnknownOpcodeError(opcode.code)
930                lastopcode = opcode.code
931        except Error, exc:
932            exc.decorate(opcode.location)
933            raise
934        except Exception, exc:
935            raise Error(exc).decorate(opcode.location)
936        indent -= 1
937        buildloc = "ul4c.Location(source, *locations[sys.exc_info()[2].tb_lineno-startline])"
938        _code("except ul4c.Error, exc:")
939        indent += 1
940        _code("exc.decorate(%s)" % buildloc)
941        _code("raise")
942        indent -= 1
943        _code("except Exception, exc:")
944        indent += 1
945        _code("raise ul4c.Error(exc).decorate(%s)" % buildloc)
946        return "\n".join(output)
947
948    def pythonfunction(self):
949        if self._pythonfunction is None:
950            code = self.pythonsource("render")
951            ns = {}
952            exec code.encode("utf-8") in ns
953            self._pythonfunction = ns["render"]
954        return self._pythonfunction
955
956    def __call__(self, templates={}, **variables):
957        return self.pythonfunction()(templates, **variables)
958
959    def render(self, templates={}, **variables):
960        return self.pythonfunction()(templates, **variables)
961
962    def renders(self, templates={}, **variables):
963        return "".join(self.render(templates, **variables))
964
965    def format(self, indent="\t"):
966        """
967        Format the list of opcodes. This is a generator yielding lines to be output
968        (but without trailing newlines). :var:`indent` can be used to specify how
969        to indent block (defaulting to ``"\\t"``).
970        """
971        i = 0
972        for opcode in self:
973            if opcode.code in ("else", "endif", "endfor"):
974                i -= 1
975            if opcode.code in ("endif", "endfor"):
976                yield "%s}" % (i*indent)
977            elif opcode.code in ("for", "if"):
978                yield "%s%s {" % (i*indent, opcode)
979            elif opcode.code == "else":
980                yield "%s} else {" % (i*indent)
981            else:
982                yield "%s%s" % (i*indent, opcode)
983            if opcode.code in ("for", "if", "else"):
984                i += 1
985
986    def _tokenize(self, source, startdelim, enddelim):
987        pattern = u"%s(print|code|for|if|elif|else|end|render)(\s*((.|\\n)*?)\s*)?%s" % (re.escape(startdelim), re.escape(enddelim))
988        pos = 0
989        for match in re.finditer(pattern, source):
990            if match.start() != pos:
991                yield Location(source, None, pos, match.start(), pos, match.start())
992            yield Location(source, source[match.start(1):match.end(1)], match.start(), match.end(), match.start(3), match.end(3))
993            pos = match.end()
994        end = len(source)
995        if pos != end:
996            yield Location(source, None, pos, end, pos, end)
997
998    def _allocreg(self):
999        try:
1000            return self.registers.pop()
1001        except KeyError:
1002            raise OutOfRegistersError()
1003
1004    def _freereg(self, register):
1005        self.registers.add(register)
1006
1007    def opcode(self, name, r1=None, r2=None, r3=None, r4=None, r5=None, arg=None):
1008        self.opcodes.append(Opcode(name, r1, r2, r3, r4, r5, arg, self.location))
1009
1010    def _compile(self, source, startdelim, enddelim):
1011        self.startdelim = startdelim
1012        self.enddelim = enddelim
1013        scanner = Scanner()
1014        parseexpr = ExprParser(scanner).compile
1015        parsestmt = StmtParser(scanner).compile
1016        parsefor = ForParser(scanner).compile
1017        parserender = RenderParser(scanner).compile
1018
1019        # This stack stores for each nested for/foritem/if/elif/else the following information:
1020        # 1) Which construct we're in (i.e. "if" or "for")
1021        # For ifs:
1022        # 2) How many if's or elif's we have seen (this is used for simulating elif's via nested if's, for each additional elif, we have one more endif to add)
1023        # 3) Whether we've already seen the else
1024        stack = []
1025
1026        self.source = source
1027        self.opcodes = []
1028
1029        for location in self._tokenize(source, startdelim, enddelim):
1030            self.location = location
1031            try:
1032                if location.type is None:
1033                    self.opcode(None)
1034                elif location.type == "print":
1035                    r = parseexpr(self)
1036                    self.opcode("print", r1=r)
1037                elif location.type == "code":
1038                    parsestmt(self)
1039                elif location.type == "if":
1040                    r = parseexpr(self)
1041                    self.opcode("if", r1=r)
1042                    stack.append(("if", 1, False))
1043                elif location.type == "elif":
1044                    if not stack or stack[-1][0] != "if":
1045                        raise BlockError("elif doesn't match any if")
1046                    elif stack[-1][2]:
1047                        raise BlockError("else already seen in elif")
1048                    self.opcode("else")
1049                    r = parseexpr(self)
1050                    self.opcode("if", r1=r)
1051                    stack[-1] = ("if", stack[-1][1]+1, False)
1052                elif location.type == "else":
1053                    if not stack or stack[-1][0] != "if":
1054                        raise BlockError("else doesn't match any if")
1055                    elif stack[-1][2]:
1056                        raise BlockError("duplicate else")
1057                    self.opcode("else")
1058                    stack[-1] = ("if", stack[-1][1], True)
1059                elif location.type == "end":
1060                    if not stack:
1061                        raise BlockError("not in any block")
1062                    code = location.code
1063                    if code:
1064                        if code == "if":
1065                            if stack[-1][0] != "if":
1066                                raise BlockError("endif doesn't match any if")
1067                        elif code == "for":
1068                            if stack[-1][0] != "for":
1069                                raise BlockError("endfor doesn't match any for")
1070                        else:
1071                            raise BlockError("illegal end value %r" % code)
1072                    last = stack.pop()
1073                    if last[0] == "if":
1074                        for i in xrange(last[1]):
1075                            self.opcode("endif")
1076                    else: # last[0] == "for":
1077                        self.opcode("endfor")
1078                elif location.type == "for":
1079                    parsefor(self)
1080                    stack.append(("for",))
1081                elif location.type == "render":
1082                    parserender(self)
1083                else: # Can't happen
1084                    raise ValueError("unknown tag %r" % location.type)
1085            except Error, exc:
1086                exc.decorate(location)
1087                raise
1088            except Exception, exc:
1089                raise Error(exc).decorate(location)
1090            finally:
1091                del self.location
1092        if stack:
1093            raise BlockError("unclosed blocks")
1094
1095    def __str__(self):
1096        return "\n".join(self.format())
1097
1098    def __unicode__(self):
1099        return u"\n".join(self.format())
1100
1101    def __repr__(self):
1102        return "<%s.%s object with %d opcodes at 0x%x>" % (self.__class__.__module__, self.__class__.__name__, len(self.opcodes), id(self))
1103
1104
1105def compile(source, startdelim="<?", enddelim="?>"):
1106    template = Template()
1107    template._compile(source, startdelim, enddelim)
1108    return template
1109
1110load = Template.load
1111loads = Template.loads
1112
1113
1114###
1115### Tokens and nodes for the AST
1116###
1117
1118class Token(object):
1119    def __init__(self, start, end, type):
1120        self.start = start
1121        self.end = end
1122        self.type = type
1123
1124    def __repr__(self):
1125        return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.type)
1126
1127    def __str__(self):
1128        return self.type
1129
1130
1131class AST(object):
1132    """
1133    Baseclass for all syntax tree nodes.
1134    """
1135
1136    def __init__(self, start, end):
1137        self.start = start
1138        self.end = end
1139
1140
1141class Const(AST):
1142    """
1143    Common baseclass for all constants (used for type testing in constant folding)
1144    """
1145
1146    def __repr__(self):
1147        return "%s(%r, %r)" % (self.__class__.__name__, self.start, self.end)
1148
1149    def compile(self, template):
1150        r = template._allocreg()
1151        template.opcode("load%s" % self.type, r1=r)
1152        return r
1153
1154
1155class None_(Const):
1156    type = "none"
1157    value = None
1158
1159
1160class True_(Const):
1161    type = "true"
1162    value = True
1163
1164
1165class False_(Const):
1166    type = "false"
1167    value = False
1168
1169
1170class Value(Const):
1171    def __init__(self, start, end, value):
1172        Const.__init__(self, start, end)
1173        self.value = value
1174
1175    def __repr__(self):
1176        return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.value)
1177
1178    def compile(self, template):
1179        r = template._allocreg()
1180        template.opcode("load%s" % self.type, r1=r, arg=unicode(self.value))
1181        return r
1182
1183
1184class Int(Value):
1185    type = "int"
1186
1187
1188class Float(Value):
1189    type = "float"
1190
1191    def compile(self, template):
1192        r = template._allocreg()
1193        template.opcode("load%s" % self.type, r1=r, arg=repr(self.value))
1194        return r
1195
1196
1197class Str(Value):
1198    type = "str"
1199
1200
1201class Date(Value):
1202    type = "date"
1203
1204    def compile(self, template):
1205        r = template._allocreg()
1206        template.opcode("load%s" % self.type, r1=r, arg=self.value.isoformat())
1207        return r
1208
1209
1210class List(AST):
1211    def __init__(self, start, end, *items):
1212        AST.__init__(self, start, end)
1213        self.items = list(items)
1214
1215    def __repr__(self):
1216        return "%s(%r, %r, %s)" % (self.__class__.__name__, self.start, self.end, repr(self.items)[1:-1])
1217
1218    def compile(self, template):
1219        r = template._allocreg()
1220        template.opcode("buildlist", r1=r)
1221        for item in self.items:
1222            ri = item.compile(template)
1223            template.opcode("addlist", r1=r, r2=ri)
1224            template._freereg(ri)
1225        return r
1226
1227
1228class Dict(AST):
1229    def __init__(self, start, end, *items):
1230        AST.__init__(self, start, end)
1231        self.items = list(items)
1232
1233    def __repr__(self):
1234        return "%s(%r, %r, %s)" % (self.__class__.__name__, self.start, self.end, repr(self.items)[1:-1])
1235
1236    def compile(self, template):
1237        r = template._allocreg()
1238        template.opcode("builddict", r1=r)
1239        for (key, value) in self.items:
1240            rk = key.compile(template)
1241            rv = value.compile(template)
1242            template.opcode("adddict", r1=r, r2=rk, r3=rv)
1243            template._freereg(rk)
1244            template._freereg(rv)
1245        return r
1246
1247
1248class Name(AST):
1249    type = "name"
1250
1251    def __init__(self, start, end, name):
1252        AST.__init__(self, start, end)
1253        self.name = name
1254
1255    def __repr__(self):
1256        return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.name)
1257
1258    def compile(self, template):
1259        r = template._allocreg()
1260        template.opcode("loadvar", r1=r, arg=self.name)
1261        return r
1262
1263
1264class For(AST):
1265    def __init__(self, start, end, iter, cont):
1266        AST.__init__(self, start, end)
1267        self.iter = iter
1268        self.cont = cont
1269
1270    def __repr__(self):
1271        return "%s(%r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.iter, self.cont)
1272
1273    def compile(self, template):
1274        rc = self.cont.compile(template)
1275        ri = template._allocreg()
1276        template.opcode("for", r1=ri, r2=rc)
1277        if isinstance(self.iter, list):
1278            for (i, iter) in enumerate(self.iter):
1279                rii = template._allocreg()
1280                template.opcode("loadint", r1=rii, arg=str(i))
1281                template.opcode("getitem", r1=rii, r2=ri, r3=rii)
1282                template.opcode("storevar", r1=rii, arg=iter.name)
1283                template._freereg(rii)
1284        else:
1285            template.opcode("storevar", r1=ri, arg=self.iter.name)
1286        template._freereg(ri)
1287        template._freereg(rc)
1288
1289
1290class GetAttr(AST):
1291    def __init__(self, start, end, obj, attr):
1292        AST.__init__(self, start, end)
1293        self.obj = obj
1294        self.attr = attr
1295
1296    def __repr__(self):
1297        return "%s(%r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.obj, self.attr)
1298
1299    def compile(self, template):
1300        r = self.obj.compile(template)
1301        template.opcode("getattr", r1=r, r2=r, arg=self.attr.name)
1302        return r
1303
1304
1305class GetSlice12(AST):
1306    def __init__(self, start, end, obj, index1, index2):
1307        AST.__init__(self, start, end)
1308        self.obj = obj
1309        self.index1 = index1
1310        self.index2 = index2
1311
1312    def __repr__(self):
1313        return "%s(%r, %r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.obj, self.index1, self.index2)
1314
1315    def compile(self, template):
1316        r1 = self.obj.compile(template)
1317        r2 = self.index1.compile(template)
1318        r3 = self.index2.compile(template)
1319        template.opcode("getslice12", r1=r1, r2=r1, r3=r2, r4=r3)
1320        template._freereg(r2)
1321        template._freereg(r3)
1322        return r1
1323
1324
1325class Unary(AST):
1326    opcode = None
1327
1328    def __init__(self, start, end, obj):
1329        AST.__init__(self, start, end)
1330        self.obj = obj
1331
1332    def __repr__(self):
1333        return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.obj)
1334
1335    def compile(self, template):
1336        r = self.obj.compile(template)
1337        template.opcode(self.opcode, r1=r, r2=r)
1338        return r
1339
1340
1341class GetSlice(Unary):
1342    opcode = "getslice"
1343
1344
1345class Not(Unary):
1346    opcode = "not"
1347
1348
1349class Neg(Unary):
1350    opcode = "neg"
1351
1352
1353class Binary(AST):
1354    opcode = None
1355
1356    def __init__(self, start, end, obj1, obj2):
1357        AST.__init__(self, start, end)
1358        self.obj1 = obj1
1359        self.obj2 = obj2
1360
1361    def __repr__(self):
1362        return "%s(%r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.obj1, self.obj2)
1363
1364    def compile(self, template):
1365        r1 = self.obj1.compile(template)
1366        r2 = self.obj2.compile(template)
1367        template.opcode(self.opcode, r1=r1, r2=r1, r3=r2)
1368        template._freereg(r2)
1369        return r1
1370
1371
1372class GetItem(Binary):
1373    opcode = "getitem"
1374
1375
1376class GetSlice1(Binary):
1377    opcode = "getslice1"
1378
1379
1380class GetSlice2(Binary):
1381    opcode = "getslice2"
1382
1383
1384class Equal(Binary):
1385    opcode = "equals"
1386
1387
1388class NotEqual(Binary):
1389    opcode = "notequals"
1390
1391
1392class Contains(Binary):
1393    opcode = "contains"
1394
1395
1396class NotContains(Binary):
1397    opcode = "notcontains"
1398
1399
1400class Add(Binary):
1401    opcode = "add"
1402
1403
1404class Sub(Binary):
1405    opcode = "sub"
1406
1407
1408class Mul(Binary):
1409    opcode = "mul"
1410
1411
1412class FloorDiv(Binary):
1413    opcode = "floordiv"
1414
1415
1416class TrueDiv(Binary):
1417    opcode = "truediv"
1418
1419
1420class Or(Binary):
1421    opcode = "or"
1422
1423
1424class And(Binary):
1425    opcode = "and"
1426
1427
1428class Mod(Binary):
1429    opcode = "mod"
1430
1431
1432class ChangeVar(AST):
1433    opcode = None
1434
1435    def __init__(self, start, end, name, value):
1436        AST.__init__(self, start, end)
1437        self.name = name
1438        self.value = value
1439
1440    def __repr__(self):
1441        return "%s(%r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.name, self.value)
1442
1443    def compile(self, template):
1444        r = self.value.compile(template)
1445        template.opcode(self.opcode, r1=r, arg=self.name.name)
1446        template._freereg(r)
1447
1448
1449class StoreVar(ChangeVar):
1450    opcode = "storevar"
1451
1452
1453class AddVar(ChangeVar):
1454    opcode = "addvar"
1455
1456
1457class SubVar(ChangeVar):
1458    opcode = "subvar"
1459
1460
1461class MulVar(ChangeVar):
1462    opcode = "mulvar"
1463
1464
1465class TrueDivVar(ChangeVar):
1466    opcode = "truedivvar"
1467
1468
1469class FloorDivVar(ChangeVar):
1470    opcode = "floordivvar"
1471
1472
1473class ModVar(ChangeVar):
1474    opcode = "modvar"
1475
1476
1477class DelVar(AST):
1478    def __init__(self, start, end, name):
1479        AST.__init__(self, start, end)
1480        self.name = name
1481
1482    def __repr__(self):
1483        return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.name)
1484
1485    def compile(self, template):
1486        template.opcode("delvar", arg=self.name.name)
1487
1488
1489class CallFunc(AST):
1490    def __init__(self, start, end, name, args):
1491        AST.__init__(self, start, end)
1492        self.name = name
1493        self.args = args
1494
1495    def __repr__(self):
1496        if self.args:
1497            return "%s(%r, %r, %r, %s)" % (self.__class__.__name__, self.start, self.end, self.name, repr(self.args)[1:-1])
1498        else:
1499            return "%s(%r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.name)
1500
1501    def compile(self, template):
1502        if len(self.args) == 0:
1503            r = template._allocreg()
1504            template.opcode("callfunc0", r1=r, arg=self.name.name)
1505            return r
1506        elif len(self.args) > 3:
1507            raise ValueError("%d arguments not supported" % len(self.args))
1508        else:
1509            rs = [arg.compile(template) for arg in self.args]
1510            template.opcode("callfunc%d" % len(self.args), rs[0], *rs, **dict(arg=self.name.name)) # Replace **dict(arg=) with arg= in Python 2.6?
1511            for i in xrange(1, len(self.args)):
1512                template._freereg(rs[i])
1513            return rs[0]
1514
1515
1516class CallMeth(AST):
1517    def __init__(self, start, end, name, obj, args):
1518        AST.__init__(self, start, end)
1519        self.name = name
1520        self.obj = obj
1521        self.args = args
1522
1523    def __repr__(self):
1524        if self.args:
1525            return "%s(%r, %r, %r, %r, %s)" % (self.__class__.__name__, self.start, self.end, self.name, self.obj, repr(self.args)[1:-1])
1526        else:
1527            return "%s(%r, %r, %r, %r)" % (self.__class__.__name__, self.start, self.end, self.name, self.obj)
1528
1529    def compile(self, template):
1530        if len(self.args) > 3:
1531            raise ValueError("%d arguments not supported" % len(self.args))
1532        ro = self.obj.compile(template)
1533        rs = [arg.compile(template) for arg in self.args]
1534        template.opcode("callmeth%d" % len(self.args), ro, ro, *rs, **dict(arg=self.name.name))
1535        for r in rs:
1536            template._freereg(r)
1537        return ro
1538
1539
1540class Render(AST):
1541    def __init__(self, start, end, name, *variables):
1542        AST.__init__(self, start, end)
1543        self.name = name
1544        self.variables = list(variables)
1545
1546    def __repr__(self):
1547        return "%s(%r, %r, %r, %s)" % (self.__class__.__name__, self.start, self.end, self.name, repr(self.variables)[1:-1])
1548
1549    def compile(self, template):
1550        r = template._allocreg()
1551        template.opcode("builddict", r1=r)
1552        for (key, value) in self.variables:
1553            rv = value.compile(template)
1554            rk = template._allocreg()
1555            template.opcode("loadstr", r1=rk, arg=key.name)
1556            template.opcode("adddict", r1=r, r2=rk, r3=rv)
1557            template._freereg(rk)
1558            template._freereg(rv)
1559        template.opcode("render", r1=r, arg=self.name.name)
1560        template._freereg(r)
1561
1562
1563###
1564### Tokenizer
1565###
1566
1567class Scanner(spark.Scanner):
1568    reflags = re.UNICODE
1569
1570    def tokenize(self, location):
1571        self.collectstr = []
1572        self.rv = []
1573        self.start = 0
1574        try:
1575            spark.Scanner.tokenize(self, location.code)
1576            if self.mode != "default":
1577                raise UnterminatedStringError()
1578        except Error, exc:
1579            exc.decorate(location)
1580            raise
1581        except Exception, exc:
1582            raise Error(exc).decorate(location)
1583        return self.rv
1584
1585    # Must be before the int and float constants
1586    @spark.token("\\d{4}-\\d{2}-\\d{2}T(\\d{2}:\\d{2}(:\\d{2}(\\.\\d{6})?)?)?", "default")
1587    def date(self, start, end, s):
1588        self.rv.append(Date(start, end, datetime.datetime(*map(int, filter(None, datesplitter.split(s))))))
1589
1590    @spark.token("\\(|\\)|\\[|\\]|\\{|\\}|\\.|,|==|\\!=|=|\\+=|\\-=|\\*=|//=|/=|%=|%|:|\\+|-|\\*|//|/", "default")
1591    def token(self, start, end, s):
1592        self.rv.append(Token(start, end, s))
1593
1594    @spark.token("[a-zA-Z_][\\w]*", "default")
1595    def name(self, start, end, s):
1596        if s in ("in", "not", "or", "and", "del"):
1597            self.rv.append(Token(start, end, s))
1598        elif s == "None":
1599            self.rv.append(None_(start, end))
1600        elif s == "True":
1601            self.rv.append(True_(start, end))
1602        elif s == "False":
1603            self.rv.append(False_(start, end))
1604        else:
1605            self.rv.append(Name(start, end, s))
1606
1607    # We don't have negatve numbers, this is handled by constant folding in the AST for unary minus
1608    @spark.token("\\d+\\.\\d*([eE][+-]?\\d+)?", "default")
1609    @spark.token("\\d+(\\.\\d*)?[eE][+-]?\\d+", "default")
1610    def float(self, start, end, s):
1611        self.rv.append(Float(start, end, float(s)))
1612
1613    @spark.token("0[xX][\\da-fA-F]+", "default")
1614    def hexint(self, start, end, s):
1615        self.rv.append(Int(start, end, int(s[2:], 16)))
1616
1617    @spark.token("0[oO][0-7]+", "default")
1618    def octint(self, start, end, s):
1619        self.rv.append(Int(start, end, int(s[2:], 8)))
1620
1621    @spark.token("0[bB][01]+", "default")
1622    def binint(self, start, end, s):
1623        self.rv.append(Int(start, end, int(s[2:], 2)))
1624
1625    @spark.token("\\d+", "default")
1626    def int(self, start, end, s):
1627        self.rv.append(Int(start, end, int(s)))
1628
1629    @spark.token("'", "default")
1630    def beginstr1(self, start, end, s):
1631        self.mode = "str1"
1632        self.start = start
1633
1634    @spark.token('"', "default")
1635    def beginstr2(self, start, end, s):
1636        self.mode = "str2"
1637        self.start = start
1638
1639    @spark.token("'", "str1")
1640    @spark.token('"', "str2")
1641    def endstr(self, start, end, s):
1642        self.rv.append(Str(self.start, end, "".join(self.collectstr)))
1643        self.collectstr = []
1644        self.mode = "default"
1645
1646    @spark.token("\\s+", "default")
1647    def whitespace(self, start, end, s):
1648        pass
1649
1650    @spark.token("\\\\\\\\", "str1", "str2")
1651    def escapedbackslash(self, start, end, s):
1652        self.collectstr.append("\\")
1653
1654    @spark.token("\\\\'", "str1", "str2")
1655    def escapedapos(self, start, end, s):
1656        self.collectstr.append("'")
1657
1658    @spark.token('\\\\"', "str1", "str2")
1659    def escapedquot(self, start, end, s):
1660        self.collectstr.append('"')
1661
1662    @spark.token("\\\\a", "str1", "str2")
1663    def escapedbell(self, start, end, s):
1664        self.collectstr.append("\a")
1665
1666    @spark.token("\\\\b", "str1", "str2")
1667    def escapedbackspace(self, start, end, s):
1668        self.collectstr.append("\b")
1669
1670    @spark.token("\\\\f", "str1", "str2")
1671    def escapedformfeed(self, start, end, s):
1672        self.collectstr.append("\f")
1673
1674    @spark.token("\\\\n", "str1", "str2")
1675    def escapedlinefeed(self, start, end, s):
1676        self.collectstr.append("\n")
1677
1678    @spark.token("\\\\r", "str1", "str2")
1679    def escapedcarriagereturn(self, start, end, s):
1680        self.collectstr.append("\r")
1681
1682    @spark.token("\\\\t", "str1", "str2")
1683    def escapedtab(self, start, end, s):
1684        self.collectstr.append("\t")
1685
1686    @spark.token("\\\\v", "str1", "str2")
1687    def escapedverticaltab(self, start, end, s):
1688        self.collectstr.append("\v")
1689
1690    @spark.token("\\\\e", "str1", "str2")
1691    def escapedescape(self, start, end, s):
1692        self.collectstr.append("\x1b")
1693
1694    @spark.token("\\\\x[0-9a-fA-F]{2}", "str1", "str2")
1695    def escaped8bitchar(self, start, end, s):
1696        self.collectstr.append(unichr(int(s[2:], 16)))
1697
1698    @spark.token("\\\\u[0-9a-fA-F]{4}", "str1", "str2")
1699    def escaped16bitchar(self, start, end, s):
1700        self.collectstr.append(unichr(int(s[2:], 16)))
1701
1702    @spark.token(".|\\n", "str1", "str2")
1703    def text(self, start, end, s):
1704        self.collectstr.append(s)
1705
1706    @spark.token("(.|\\n)+", "default", "str1", "str2")
1707    def default(self, start, end, s):
1708        raise LexicalError(start, end, s)
1709
1710    def error(self, start, end, s):
1711        raise LexicalError(start, end, s)
1712
1713
1714###
1715### Parsers for different types of code
1716###
1717
1718class ExprParser(spark.Parser):
1719    emptyerror = "expression required"
1720    start = "expr0"
1721
1722    def __init__(self, scanner):
1723        spark.Parser.__init__(self)
1724        self.scanner = scanner
1725
1726    def compile(self, template):
1727        location = template.location
1728        if not location.code:
1729            raise ValueError(self.emptyerror)
1730        template.registers = set(xrange(10))
1731        try:
1732            ast = self.parse(self.scanner.tokenize(location))
1733            return ast.compile(template)
1734        except Error, exc:
1735            exc.decorate(location)
1736            raise
1737        except Exception, exc:
1738            raise Error(exc).decorate(location)
1739        finally:
1740            del template.registers
1741
1742    def typestring(self, token):
1743        return token.type
1744
1745    def error(self, token):
1746        raise SyntaxError(token)
1747
1748    def makeconst(self, start, end, value):
1749        if value is None:
1750            return None_(start, end)
1751        elif value is True:
1752            return True_(start, end)
1753        elif value is False:
1754            return False_(start, end)
1755        elif isinstance(value, int):
1756            return Int(start, end, value)
1757        elif isinstance(value, float):
1758            return Float(start, end, value)
1759        elif isinstance(value, basestring):
1760            return Str(start, end, value)
1761        else:
1762            raise TypeError("can't convert %r" % value)
1763
1764    # To implement operator precedence, each expression rule has the precedence in its name. The highest precedence is 11 for atomic expressions.
1765    # Each expression can have only expressions as parts, which have the some or a higher precedence with two exceptions:
1766    #    1) Expressions where there's no ambiguity, like the index for a getitem/getslice or function/method arguments;
1767    #    2) Brackets, which can be used to boost the precedence of an expression to the level of an atomic expression.
1768
1769    @spark.production('expr11 ::= none')
1770    @spark.production('expr11 ::= true')
1771    @spark.production('expr11 ::= false')
1772    @spark.production('expr11 ::= str')
1773    @spark.production('expr11 ::= int')
1774    @spark.production('expr11 ::= float')
1775    @spark.production('expr11 ::= date')
1776    @spark.production('expr11 ::= name')
1777    def expr_atom(self, atom):
1778        return atom
1779
1780    @spark.production('expr11 ::= [ ]')
1781    def expr_emptylist(self, _0, _1):
1782        return List(_0.start, _1.end)
1783
1784    @spark.production('buildlist ::= [ expr0')
1785    def expr_buildlist(self, _0, expr):
1786        return List(_0.start, expr.end, expr)
1787
1788    @spark.production('buildlist ::= buildlist , expr0')
1789    def expr_addlist(self, list, _0, expr):
1790        list.items.append(expr)
1791        list.end = expr.end
1792        return list
1793
1794    @spark.production('expr11 ::= buildlist ]')
1795    def expr_finishlist(self, list, _0):
1796        list.end = _0.end
1797        return list
1798
1799    @spark.production('expr11 ::= buildlist , ]')
1800    def expr_finishlist1(self, list, _0, _1):
1801        list.end = _1.end
1802        return list
1803
1804    @spark.production('expr11 ::= { }')
1805    def expr_emptydict(self, _0, _1):
1806        return Dict(_0.start, _1.end)
1807
1808    @spark.production('builddict ::= { expr0 : expr0')
1809    def expr_builddict(self, _0, exprkey, _1, exprvalue):
1810        return Dict(_0.start, exprvalue.end, (exprkey, exprvalue))
1811
1812    @spark.production('builddict ::= builddict , expr0 : expr0')
1813    def expr_adddict(self, dict, _0, exprkey, _1, exprvalue):
1814        dict.items.append((exprkey, exprvalue))
1815        dict.end = exprvalue.end
1816        return dict
1817
1818    @spark.production('expr11 ::= builddict }')
1819    def expr_finishdict(self, dict, _0):
1820        dict.end = _0.end
1821        return dict
1822
1823    @spark.production('expr11 ::= builddict , }')
1824    def expr_finishdict1(self, dict, _0, _1):
1825        dict.end = _1.end
1826        return dict
1827
1828    @spark.production('expr11 ::= ( expr0 )')
1829    def expr_bracket(self, _0, expr, _1):
1830        return expr
1831
1832    @spark.production('expr10 ::= name ( )')
1833    def expr_callfunc0(self, name, _0, _1):
1834        return CallFunc(name.start, _1.end, name, [])
1835
1836    @spark.production('expr10 ::= name ( expr0 )')
1837    def expr_callfunc1(self, name, _0, arg0, _1):
1838        return CallFunc(name.start, _1.end, name, [arg0])
1839
1840    @spark.production('expr10 ::= name ( expr0 , expr0 )')
1841    def expr_callfunc2(self, name, _0, arg0, _1, arg1, _2):
1842        return CallFunc(name.start, _2.end, name, [arg0, arg1])
1843
1844    @spark.production('expr10 ::= name ( expr0 , expr0 , expr0 )')
1845    def expr_callfunc3(self, name, _0, arg0, _1, arg1, _2, arg2, _3):
1846        return CallFunc(name.start, _3.end, name, [arg0, arg1, arg2])
1847
1848    @spark.production('expr9 ::= expr9 . name')
1849    def expr_getattr(self, expr, _0, name):
1850        return GetAttr(expr.start, name.end, expr, name)
1851
1852    @spark.production('expr9 ::= expr9 . name ( )')
1853    def expr_callmeth0(self, expr, _0, name, _1, _2):
1854        return CallMeth(expr.start, _2.end, name, expr, [])
1855
1856    @spark.production('expr9 ::= expr9 . name ( expr0 )')
1857    def expr_callmeth1(self, expr, _0, name, _1, arg1, _2):
1858        return CallMeth(expr.start, _2.end, name, expr, [arg1])
1859
1860    @spark.production('expr9 ::= expr9 . name ( expr0 , expr0 )')
1861    def expr_callmeth2(self, expr, _0, name, _1, arg1, _2, arg2, _3):
1862        return CallMeth(expr.start, _3.end, name, expr, [arg1, arg2])
1863
1864    @spark.production('expr9 ::= expr9 . name ( expr0 , expr0 , expr0 )')
1865    def expr_callmeth3(self, expr, _0, name, _1, arg1, _2, arg2, _3, arg3, _4):
1866        return CallMeth(expr.start, _4.end, name, expr, [arg1, arg2, arg3])
1867
1868    @spark.production('expr9 ::= expr9 [ expr0 ]')
1869    def expr_getitem(self, expr, _0, key, _1):
1870        if isinstance(expr, Const) and isinstance(key, Const): # Constant folding
1871            return self.makeconst(expr.start, _1.end, expr.value[key.value])
1872        return GetItem(expr.start, _1.end, expr, key)
1873
1874    @spark.production('expr8 ::= expr8 [ expr0 : expr0 ]')
1875    def expr_getslice12(self, expr, _0, index1, _1, index2, _2):
1876        if isinstance(expr, Const) and isinstance(index1, Const) and isinstance(index2, Const): # Constant folding
1877            return self.makeconst(expr.start, _2.end, expr.value[index1.value:index1.value])
1878        return GetSlice12(expr.start, _2.end, expr, index1, index2)
1879
1880    @spark.production('expr8 ::= expr8 [ expr0 : ]')
1881    def expr_getslice1(self, expr, _0, index1, _1, _2):
1882        if isinstance(expr, Const) and isinstance(index1, Const): # Constant folding
1883            return self.makeconst(expr.start, _2.end, expr.value[index1.value:])
1884        return GetSlice1(expr.start, _2.end, expr, index1)
1885
1886    @spark.production('expr8 ::= expr8 [ : expr0 ]')
1887    def expr_getslice2(self, expr, _0, _1, index2, _2):
1888        if isinstance(expr, Const) and isinstance(index2, Const): # Constant folding
1889            return self.makeconst(expr.start, _2.end, expr.value[:index2.value])
1890        return GetSlice2(expr.start, _2.end, expr, index2)
1891
1892    @spark.production('expr8 ::= expr8 [ : ]')
1893    def expr_getslice(self, expr, _0, _1, _2):
1894        if isinstance(expr, Const): # Constant folding
1895            return self.makeconst(expr.start, _2.end, expr.value[:])
1896        return GetSlice(expr.start, _2.end, expr)
1897
1898    @spark.production('expr7 ::= - expr7')
1899    def expr_neg(self, _0, expr):
1900        if isinstance(expr, Const): # Constant folding
1901            return self.makeconst(_0.start, expr.end, -expr.value)
1902        return Neg(_0.start, expr.end, expr)
1903
1904    @spark.production('expr6 ::= expr6 * expr6')
1905    def expr_mul(self, obj1, _0, obj2):
1906        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1907            return self.makeconst(obj1.start, obj2.end, obj1.value * obj2.value)
1908        return Mul(obj1.start, obj2.end, obj1, obj2)
1909
1910    @spark.production('expr6 ::= expr6 // expr6')
1911    def expr_floordiv(self, obj1, _0, obj2):
1912        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1913            return self.makeconst(obj1.start, obj2.end, obj1.value // obj2.value)
1914        return FloorDiv(obj1.start, obj2.end, obj1, obj2)
1915
1916    @spark.production('expr6 ::= expr6 / expr6')
1917    def expr_truediv(self, obj1, _0, obj2):
1918        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1919            return self.makeconst(obj1.start, obj2.end, obj1.value / obj2.value)
1920        return TrueDiv(obj1.start, obj2.end, obj1, obj2)
1921
1922    @spark.production('expr6 ::= expr6 % expr6')
1923    def expr_mod(self, obj1, _0, obj2):
1924        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1925            return self.makeconst(obj1.start, obj2.end, obj1.value % obj2.value)
1926        return Mod(obj1.start, obj2.end, obj1, obj2)
1927
1928    @spark.production('expr5 ::= expr5 + expr5')
1929    def expr_add(self, obj1, _0, obj2):
1930        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1931            return self.makeconst(obj1.start, obj2.end, obj1.value + obj2.value)
1932        return Add(obj1.start, obj2.end, obj1, obj2)
1933
1934    @spark.production('expr5 ::= expr5 - expr5')
1935    def expr_sub(self, obj1, _0, obj2):
1936        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1937            return self.makeconst(obj1.start, obj2.end, obj1.value - obj2.value)
1938        return Sub(obj1.start, obj2.end, obj1, obj2)
1939
1940    @spark.production('expr4 ::= expr4 == expr4')
1941    def expr_equal(self, obj1, _0, obj2):
1942        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1943            return self.makeconst(obj1.start, obj2.end, obj1.value == obj2.value)
1944        return Equal(obj1.start, obj2.end, obj1, obj2)
1945
1946    @spark.production('expr4 ::= expr4 != expr4')
1947    def expr_notequal(self, obj1, _0, obj2):
1948        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1949            return self.makeconst(obj1.start, obj2.end, obj1.value != obj2.value)
1950        return NotEqual(obj1.start, obj2.end, obj1, obj2)
1951
1952    @spark.production('expr3 ::= expr3 in expr3')
1953    def expr_contains(self, obj, _0, container):
1954        if isinstance(obj, Const) and isinstance(container, Const): # Constant folding
1955            return self.makeconst(obj.start, container.end, obj.value in container.value)
1956        return Contains(obj.start, container.end, obj, container)
1957
1958    @spark.production('expr3 ::= expr3 not in expr3')
1959    def expr_notcontains(self, obj, _0, _1, container):
1960        if isinstance(obj, Const) and isinstance(container, Const): # Constant folding
1961            return self.makeconst(obj.start, container.end, obj.value not in container.value)
1962        return NotContains(obj.start, container.end, obj, container)
1963
1964    @spark.production('expr2 ::= not expr2')
1965    def expr_not(self, _0, expr):
1966        if isinstance(expr1, Const): # Constant folding
1967            return self.makeconst(_0.start, expr.end, not expr.value)
1968        return Not(_0.start, expr.end, expr)
1969
1970    @spark.production('expr1 ::= expr1 and expr1')
1971    def expr_and(self, obj1, _0, obj2):
1972        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1973            return self.makeconst(obj1.start, obj2.end, bool(obj1.value and obj2.value))
1974        return And(obj1.start, obj2.end, obj1, obj2)
1975
1976    @spark.production('expr0 ::= expr0 or expr0')
1977    def expr_or(self, obj1, _0, obj2):
1978        if isinstance(obj1, Const) and isinstance(obj2, Const): # Constant folding
1979            return self.makeconst(obj1.start, obj2.end, bool(obj1.value or obj2.value))
1980        return Or(obj1.start, obj2.end, obj1, obj2)
1981
1982    # These rules make operators of different precedences interoperable, by allowing an expression to "drop" its precedence.
1983    @spark.production('expr10 ::= expr11')
1984    @spark.production('expr9 ::= expr10')
1985    @spark.production('expr8 ::= expr9')
1986    @spark.production('expr7 ::= expr8')
1987    @spark.production('expr6 ::= expr7')
1988    @spark.production('expr5 ::= expr6')
1989    @spark.production('expr4 ::= expr5')
1990    @spark.production('expr3 ::= expr4')
1991    @spark.production('expr2 ::= expr3')
1992    @spark.production('expr1 ::= expr2')
1993    @spark.production('expr0 ::= expr1')
1994    def expr_dropprecedence(self, expr):
1995        return expr
1996
1997
1998class ForParser(ExprParser):
1999    emptyerror = "loop expression required"
2000    start = "for"
2001   
2002    @spark.production('for ::= name in expr0')
2003    def for0(self, iter, _0, cont):
2004        return For(iter.start, cont.end, iter, cont)
2005
2006    @spark.production('for ::= ( name , ) in expr0')
2007    def for1(self, _0, iter, _1, _2, _3, cont):
2008        return For(_0.start, cont.end, [iter], cont)
2009
2010    @spark.production('for ::= ( name , name ) in expr0')
2011    def for2a(self, _0, iter1, _1, iter2, _2, _3, cont):
2012        return For(_0.start, cont.end, [iter1, iter2], cont)
2013
2014    @spark.production('for ::= ( name , name , ) in expr0')
2015    def for2b(self, _0, iter1, _1, iter2, _2, _3, _4, cont):
2016        return For(_0.start, cont.end, [iter1, iter2], cont)
2017
2018
2019class StmtParser(ExprParser):
2020    emptyerror = "statement required"
2021    start = "stmt"
2022
2023    @spark.production('stmt ::= name = expr0')
2024    def stmt_assign(self, name, _0, value):
2025        return StoreVar(name.start, value.end, name, value)
2026
2027    @spark.production('stmt ::= name += expr0')
2028    def stmt_iadd(self, name, _0, value):
2029        return AddVar(name.start, value.end, name, value)
2030
2031    @spark.production('stmt ::= name -= expr0')
2032    def stmt_isub(self, name, _0, value):
2033        return SubVar(name.start, value.end, name, value)
2034
2035    @spark.production('stmt ::= name *= expr0')
2036    def stmt_imul(self, name, _0, value):
2037        return MulVar(name.start, value.end, name, value)
2038
2039    @spark.production('stmt ::= name /= expr0')
2040    def stmt_itruediv(self, name, _0, value):
2041        return TrueDivVar(name.start, value.end, name, value)
2042
2043    @spark.production('stmt ::= name //= expr0')
2044    def stmt_ifloordiv(self, name, _0, value):
2045        return FloorDivVar(name.start, value.end, name, value)
2046
2047    @spark.production('stmt ::= name %= expr0')
2048    def stmt_imod(self, name, _0, value):
2049        return ModVar(name.start, value.end, name, value)
2050
2051    @spark.production('stmt ::= del name')
2052    def stmt_del(self, _0, name):
2053        return DelVar(_0.start, name.end, name)
2054
2055
2056class RenderParser(ExprParser):
2057    emptyerror = "render statement required"
2058    start = "render"
2059
2060    @spark.production('render ::= name ( )')
2061    def emptyrender(self, name, _0, _1):
2062        return Render(name.start, _1.end, name)
2063
2064    @spark.production('buildrender ::= name ( name = expr0')
2065    def startrender(self, name, _0, argname, _1, argvalue):
2066        return Render(name.start, argvalue.end, name, (argname, argvalue))
2067
2068    @spark.production('buildrender ::= buildrender , name = expr0')
2069    def buildrender(self, render, _0, argname, _1, argvalue):
2070        render.variables.append((argname, argvalue))
2071        render.end = argvalue.end
2072        return render
2073
2074    @spark.production('render ::= buildrender )')
2075    def finishrender(self, render, _0):
2076        render.end = _0.end
2077        return render
2078
2079    @spark.production('render ::= buildrender , )')
2080    def finishrender1(self, render, _0, _1):
2081        render.end = _1.end
2082        return render
2083
2084
2085###
2086### Helper functions use at template runtime
2087###
2088
2089def _oct(value):
2090    """
2091    Helper for the ``oct`` function.
2092    """
2093    if value == 0:
2094        return "0o0"
2095    elif value < 0:
2096        return "-0o" + oct(value)[2:]
2097    else:
2098        return "0o" + oct(value)[1:]
2099
2100
2101def _bin(value):
2102    """
2103    Helper for the ``bin`` function.
2104    """
2105    if value == 0:
2106        return "0b0"
2107    if value < 0:
2108        value = -value
2109        prefix = "-0b"
2110    else:
2111        prefix = "0b"
2112    v = []
2113    while value:
2114        v.append(str(value&1))
2115        value >>= 1
2116    return prefix+"".join(v)[::-1]
2117
2118
2119def _format(obj, format):
2120    """
2121    Helper for the ``format`` method.
2122    """
2123    if isinstance(obj, datetime.datetime):
2124        if "%f" in format:
2125            format = format.replace("%f", "%06d" % obj.microsecond) # FIXME: This would replace "%%f", which is wrong (wait for Python 2.6)
2126        return obj.strftime(format.encode("utf-8")) # FIXME: We shouldn't have to encode the format string (wait for Python 3.0)
2127    elif obj is None or isinstance(obj, (int, long, float, str, unicode)):
2128        from ll import stringformat
2129        return stringformat.format_builtin_type(obj, format)
2130    else:
2131        return obj.format(format) # This will raise an ``AttributeError``
2132
2133
2134def _repr(obj):
2135    """
2136    Helper for the ``repr`` function.
2137    """
2138    if isinstance(obj, unicode):
2139        return unicode(repr(obj)[1:])
2140    elif isinstance(obj, datetime.datetime):
2141        return unicode(obj.isoformat())
2142    elif isinstance(obj, list):
2143        return u"[%s]" % u", ".join(_repr(item) for item in obj)
2144    elif isinstance(obj, dict):
2145        return u"{%s}" % u", ".join(u"%s: %s" % (_repr(key), _repr(value)) for (key, value) in obj.iteritems())
2146    else:
2147        return unicode(repr(obj))
Note: See TracBrowser for help on using the browser.