root/livinglogic.java.ul4/library/src/com/livinglogic/ul4/ul4c.py @ 202:6f3968e7da58

Revision 202:6f3968e7da58, 21.4 KB (checked in by Walter Doerwald <walter@…>, 10 years ago)

Add support for the render method to Template.

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
11import sys, re, StringIO
12
13import spark
14
15from com.livinglogic import ul4
16
17from java import lang
18
19###
20### helper functions for compiling
21###
22
23def _compile(template, tags):
24    opcodes = []
25    parseexpr = ExprParser().compile
26    parsestmt = StmtParser().compile
27    parsefor = ForParser().compile
28    parserender = RenderParser().compile
29
30    # This stack stores for each nested for/foritem/if/elif/else the following information:
31    # 1) Which construct we're in (i.e. "if" or "for")
32    # 2) The start location of the construct
33    # For ifs:
34    # 3) 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)
35    # 4) Whether we've already seen the else
36    stack = []
37    for location in tags:
38        try:
39            if location.type is None:
40                template.opcode(ul4.Opcode.OC_TEXT, location)
41            elif location.type == "print":
42                r = parseexpr(template, location)
43                template.opcode(ul4.Opcode.OC_PRINT, r, location)
44            elif location.type == "printx":
45                r = parseexpr(template, location)
46                template.opcode(ul4.Opcode.OC_PRINTX, r, location)
47            elif location.type == "code":
48                parsestmt(template, location)
49            elif location.type == "if":
50                r = parseexpr(template, location)
51                template.opcode(ul4.Opcode.OC_IF, r, location)
52                stack.append(("if", location, 1, False))
53            elif location.type == "elif":
54                if not stack or stack[-1][0] != "if":
55                    raise ul4.BlockException("elif doesn't match any if")
56                elif stack[-1][2]:
57                    raise ul4.BlockException("else already seen in elif")
58                template.opcode(ul4.Opcode.OC_ELSE, location)
59                r = parseexpr(template, location)
60                template.opcode(ul4.Opcode.OC_IF, r, location)
61                stack[-1] = ("if", stack[-1][1]+1, stack[-1][2], False)
62            elif location.type == "else":
63                if not stack or stack[-1][0] != "if":
64                    raise ul4.BlockException("else doesn't match any if")
65                elif stack[-1][3]:
66                    raise ul4.BlockException("duplicate else")
67                template.opcode(ul4.Opcode.OC_ELSE, location)
68                stack[-1] = ("if", stack[-1][1], stack[-1][2], True)
69            elif location.type == "end":
70                if not stack:
71                    raise ul4.BlockException("not in any block")
72                code = location.code
73                if code:
74                    if code == "if":
75                        if stack[-1][0] != "if":
76                            raise ul4.BlockException("endif doesn't match any if")
77                    elif code == "for":
78                        if stack[-1][0] != "for":
79                            raise ul4.BlockException("endfor doesn't match any for")
80                    else:
81                        raise ul4.BlockException("illegal end value %r" % code)
82                last = stack.pop()
83                if last[0] == "if":
84                    for i in xrange(last[2]):
85                        template.opcode(ul4.Opcode.OC_ENDIF, location)
86                else: # last[0] == "for":
87                    template.opcode(ul4.Opcode.OC_ENDFOR, location)
88            elif location.type == "for":
89                parsefor(template, location)
90                stack.append(("for", location))
91            elif location.type == "break":
92                for entry in stack:
93                    if entry[0] == "for":
94                        break
95                else:
96                    raise BlockError("break outside of for loop")
97                template.opcode(ul4.Opcode.OC_BREAK, location)
98            elif location.type == "continue":
99                for entry in stack:
100                    if entry[0] == "for":
101                        break
102                else:
103                    raise BlockError("continue outside of for loop")
104                template.opcode(ul4.Opcode.OC_CONTINUE, location)
105            elif location.type == "render":
106                parserender(template, location)
107            else: # Can't happen
108                raise ValueError("unknown tag %r" % location.type)
109        except ul4.LocationException, exc:
110            raise
111        except lang.Exception, exc:
112            raise ul4.LocationException(exc, location)
113    if stack:
114        raise ul4.LocationException(ul4.BlockException("block unclosed"), stack[-1][1])
115    return opcodes
116
117
118###
119### Parsers for different types of code
120###
121
122class ExprParser(spark.GenericParser):
123    emptyerror = "expression required"
124
125    def __init__(self, start="expr0"):
126        spark.GenericParser.__init__(self, start)
127
128    def compile(self, template, location):
129        if not location.code:
130            raise ValueError(self.emptyerror)
131        try:
132            ast = self.parse(ul4.Template.tokenizeCode(location))
133            registers = ul4.Registers()
134            return ast.compile(template, registers, location)
135        except ul4.LocationException, exc:
136            raise
137        except lang.Exception, exc:
138            raise ul4.LocationException(exc, location)
139
140    def typestring(self, token):
141        return token.getTokenType()
142
143    def error(self, token):
144        raise ul4.SyntaxException(token)
145
146    def makeconst(self, start, end, value):
147        if value is None:
148            return ul4.LoadNone(start, end)
149        elif value is True:
150            return ul4.LoadTrue(start, end)
151        elif value is False:
152            return ul4.LoadFalse(start, end)
153        elif isinstance(value, int):
154            return ul4.LoadInt(start, end, value)
155        elif isinstance(value, float):
156            return ul4.LoadFloat(start, end, value)
157        elif isinstance(value, basestring):
158            return ul4.LoadStr(start, end, value)
159        else:
160            raise TypeError("can't convert %r" % value)
161
162    # To implement operator precedence, each expression rule has the precedence in its name. The highest precedence is 11 for atomic expressions.
163    # Each expression can have only expressions as parts, which have the some or a higher precedence with two exceptions:
164    #    1) Expressions where there's no ambiguity, like the index for a getitem/getslice or function/method arguments;
165    #    2) Brackets, which can be used to boost the precedence of an expression to the level of an atomic expression.
166
167    def expr_atomic(self, (atom,)):
168        return atom
169    expr_atomic.spark = [
170        'expr11 ::= none',
171        'expr11 ::= true',
172        'expr11 ::= false',
173        'expr11 ::= str',
174        'expr11 ::= int',
175        'expr11 ::= float',
176        'expr11 ::= date',
177        'expr11 ::= color',
178        'expr11 ::= name',
179    ]
180
181    def expr_emptylist(self, (_0, _1)):
182        return ul4.List(_0.start, _1.end)
183    expr_emptylist.spark = ['expr11 ::= [ ]']
184
185    def expr_buildlist(self, (_0, expr)):
186        list = ul4.List(_0.start, expr.end)
187        list.append(expr)
188        return list
189    expr_buildlist.spark = ['buildlist ::= [ expr0']
190
191    def expr_addlist(self, (list, _0, expr)):
192        list.append(expr)
193        list.end = expr.end
194        return list
195    expr_addlist.spark = ['buildlist ::= buildlist , expr0']
196
197    def expr_finishlist(self, (list, _0)):
198        list.end = _0.end
199        return list
200    expr_finishlist.spark = ['expr11 ::= buildlist ]']
201
202    def expr_finishlist1(self, (list, _0, _1)):
203        list.end = _1.end
204        return list
205    expr_finishlist1.spark = ['expr11 ::= buildlist , ]']
206
207    def expr_emptydict(self, (_0, _1)):
208        return ul4.Dict(_0.start, _1.end)
209    expr_emptydict.spark = ['expr11 ::= { }']
210
211    def expr_builddict(self, (_0, key, _1, value)):
212        dict = ul4.Dict(_0.start, value.end)
213        dict.append(key, value)
214        return dict
215    expr_builddict.spark = ['builddict ::= { expr0 : expr0']
216
217    def expr_builddictupdate(self, (_0, _1, value)):
218        dict = ul4.Dict(_0.start, value.end)
219        dict.append(value)
220        return dict
221    expr_builddictupdate.spark = ['builddict ::= { ** expr0']
222
223    def expr_adddict(self, (dict, _0, key, _1, value)):
224        dict.append(key, value)
225        dict.end = value.end
226        return dict
227    expr_adddict.spark = ['builddict ::= builddict , expr0 : expr0']
228
229    def expr_updatedict(self, (dict, _0, _1, value)):
230        dict.append(value)
231        dict.end = value.end
232        return dict
233    expr_updatedict.spark = ['builddict ::= builddict , ** expr0']
234
235    def expr_finishdict(self, (dict, _0)):
236        dict.end = _0.end
237        return dict
238    expr_finishdict.spark = ['expr11 ::= builddict }']
239
240    def expr_finishdict1(self, (dict, _0, _1)):
241        dict.end = _1.end
242        return dict
243    expr_finishdict1.spark = ['expr11 ::= builddict , }']
244
245    def expr_bracket(self, (_0, expr, _1)):
246        return expr
247    expr_bracket.spark = ['expr11 ::= ( expr0 )']
248
249    def expr_callfunc0(self, (name, _0, _1)):
250        return ul4.CallFunc(name.start, _1.end, name)
251    expr_callfunc0.spark = ['expr10 ::= name ( )']
252
253    def expr_callfunc1(self, (name, _0, arg0, _1)):
254        return ul4.CallFunc(name.start, _1.end, name, arg0)
255    expr_callfunc1.spark = ['expr10 ::= name ( expr0 )']
256
257    def expr_callfunc2(self, (name, _0, arg0, _1, arg1, _2)):
258        return ul4.CallFunc(name.start, _2.end, name, arg0, arg1)
259    expr_callfunc2.spark = ['expr10 ::= name ( expr0 , expr0 )']
260
261    def expr_callfunc3(self, (name, _0, arg0, _1, arg1, _2, arg2, _3)):
262        return ul4.CallFunc(name.start, _3.end, name, arg0, arg1, arg2)
263    expr_callfunc3.spark = ['expr10 ::= name ( expr0 , expr0 , expr0 )']
264
265    def expr_callfunc4(self, (name, _0, arg0, _1, arg1, _2, arg2, _3, arg3, _4)):
266        return ul4.CallFunc(name.start, _4.end, name, arg0, arg1, arg2, arg3)
267    expr_callfunc4.spark = ['expr10 ::= name ( expr0 , expr0 , expr0 , expr0 )']
268
269    def expr_getattr(self, (expr, _0, name)):
270        return ul4.GetAttr(expr.start, name.end, expr, name)
271    expr_getattr.spark = ['expr9 ::= expr9 . name']
272
273    def expr_callmeth0(self, (expr, _0, name, _1, _2)):
274        return ul4.CallMeth(expr.start, _2.end, expr, name)
275    expr_callmeth0.spark = ['expr9 ::= expr9 . name ( )']
276
277    def expr_callmeth1(self, (expr, _0, name, _1, arg1, _2)):
278        return ul4.CallMeth(expr.start, _2.end, expr, name, arg1)
279    expr_callmeth1.spark = ['expr9 ::= expr9 . name ( expr0 )']
280
281    def expr_callmeth2(self, (expr, _0, name, _1, arg1, _2, arg2, _3)):
282        return ul4.CallMeth(expr.start, _3.end, expr, name, arg1, arg2)
283    expr_callmeth2.spark = ['expr9 ::= expr9 . name ( expr0 , expr0 )']
284
285    def expr_callmeth3(self, (expr, _0, name, _1, arg1, _2, arg2, _3, arg3, _4)):
286        return ul4.CallMeth(expr.start, _4.end, expr, name, arg1, arg2, arg3)
287    expr_callmeth3.spark = ['expr9 ::= expr9 . name ( expr0 , expr0 , expr0 )']
288
289    def methkw_startname(self, (expr, _0, methname, _1, argname, _2, argvalue)):
290        call = ul4.CallMethKeywords(expr.start, argvalue.end, methname, expr)
291        call.append(argname.value, argvalue)
292        return call
293    methkw_startname.spark = ['callmethkw ::= expr9 . name ( name = expr0']
294
295    def methkw_startdict(self, (expr, _0, methname, _1, _2, argvalue)):
296        call = ul4.CallMethKeywords(expr.start, argvalue.end, methname, expr)
297        call.append(argvalue)
298        return call
299    methkw_startdict.spark = ['callmethkw ::= expr9 . name ( ** expr0']
300
301    def methkw_buildname(self, (call, _0, argname, _1, argvalue)):
302        call.args.append(argname.value, argvalue)
303        call.end = argvalue.end
304        return call
305    methkw_buildname.spark = ['callmethkw ::= callmethkw , name = expr0']
306
307    def methkw_builddict(self, (call, _0, _1, argvalue)):
308        call.args.append(argvalue)
309        call.end = argvalue.end
310        return call
311    methkw_builddict.spark = ['callmethkw ::= callmethkw , ** expr0']
312
313    def methkw_finish(self, (call, _0)):
314        call.end = _0.end
315        return call
316    methkw_finish.spark = ['expr9 ::= callmethkw )']
317
318    def expr_getitem(self, (expr, _0, key, _1)):
319        if isinstance(expr, ul4.LoadConst) and isinstance(key, ul4.LoadConst): # Constant folding
320            return self.makeconst(expr.start, _1.end, expr.value[key.value])
321        return ul4.GetItem(expr.start, _1.end, expr, key)
322    expr_getitem.spark = ['expr9 ::= expr9 [ expr0 ]']
323
324    def expr_getslice12(self, (expr, _0, index1, _1, index2, _2)):
325        if isinstance(expr, ul4.LoadConst) and isinstance(index1, ul4.LoadConst) and isinstance(index2, ul4.LoadConst): # Constant folding
326            return self.makeconst(expr.start, _2.end, expr.value[index1.value:index1.value])
327        return ul4.GetSlice12(expr.start, _2.end, expr, index1, index2)
328    expr_getslice12.spark = ['expr8 ::= expr8 [ expr0 : expr0 ]']
329
330    def expr_getslice1(self, (expr, _0, index1, _1, _2)):
331        if isinstance(expr, ul4.LoadConst) and isinstance(index1, ul4.LoadConst): # Constant folding
332            return self.makeconst(expr.start, _2.end, expr.value[index1.value:])
333        return ul4.GetSlice1(expr.start, _2.end, expr, index1)
334    expr_getslice1.spark = ['expr8 ::= expr8 [ expr0 : ]']
335
336    def expr_getslice2(self, (expr, _0, _1, index2, _2)):
337        if isinstance(expr, ul4.LoadConst) and isinstance(index2, ul4.LoadConst): # Constant folding
338            return self.makeconst(expr.start, _2.end, expr.value[:index2.value])
339        return ul4.GetSlice2(expr.start, _2.end, expr, index2)
340    expr_getslice2.spark = ['expr8 ::= expr8 [ : expr0 ]']
341
342    def expr_neg(self, (_0, expr)):
343        if isinstance(expr, ul4.LoadConst): # Constant folding
344            return self.makeconst(_0.start, expr.end, -expr.value)
345        return ul4.Neg(_0.start, expr.end, expr)
346    expr_neg.spark = ['expr7 ::= - expr7']
347
348    def expr_mul(self, (obj1, _0, obj2)):
349        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
350            return self.makeconst(obj1.start, obj2.end, obj1.value * obj2.value)
351        return ul4.Mul(obj1.start, obj2.end, obj1, obj2)
352    expr_mul.spark = ['expr6 ::= expr6 * expr6']
353
354    def expr_floordiv(self, (obj1, _0, obj2)):
355        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
356            return self.makeconst(obj1.start, obj2.end, obj1.value // obj2.value)
357        return ul4.FloorDiv(obj1.start, obj2.end, obj1, obj2)
358    expr_floordiv.spark = ['expr6 ::= expr6 // expr6']
359
360    def expr_truediv(self, (obj1, _0, obj2)):
361        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
362            return self.makeconst(obj1.start, obj2.end, obj1.value / obj2.value)
363        return ul4.TrueDiv(obj1.start, obj2.end, obj1, obj2)
364    expr_truediv.spark = ['expr6 ::= expr6 / expr6']
365
366    def expr_mod(self, (obj1, _0, obj2)):
367        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
368            return self.makeconst(obj1.start, obj2.end, obj1.value % obj2.value)
369        return ul4.Mod(obj1.start, obj2.end, obj1, obj2)
370    expr_mod.spark = ['expr6 ::= expr6 % expr6']
371
372    def expr_add(self, (obj1, _0, obj2)):
373        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
374            return self.makeconst(obj1.start, obj2.end, obj1.value + obj2.value)
375        return ul4.Add(obj1.start, obj2.end, obj1, obj2)
376    expr_add.spark = ['expr5 ::= expr5 + expr5']
377
378    def expr_sub(self, (obj1, _0, obj2)):
379        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
380            return self.makeconst(obj1.start, obj2.end, obj1.value - obj2.value)
381        return ul4.Sub(obj1.start, obj2.end, obj1, obj2)
382    expr_sub.spark = ['expr5 ::= expr5 - expr5']
383
384    def expr_eq(self, (obj1, _0, obj2)):
385        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
386            return self.makeconst(obj1.start, obj2.end, obj1.value == obj2.value)
387        return ul4.EQ(obj1.start, obj2.end, obj1, obj2)
388    expr_eq.spark = ['expr4 ::= expr4 == expr4']
389
390    def expr_ne(self, (obj1, _0, obj2)):
391        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
392            return self.makeconst(obj1.start, obj2.end, obj1.value != obj2.value)
393        return ul4.NE(obj1.start, obj2.end, obj1, obj2)
394    expr_ne.spark = ['expr4 ::= expr4 != expr4']
395
396    def expr_lt(self, (obj1, _0, obj2)):
397        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
398            return self.makeconst(obj1.start, obj2.end, obj1.value < obj2.value)
399        return ul4.LT(obj1.start, obj2.end, obj1, obj2)
400    expr_lt.spark = ['expr4 ::= expr4 < expr4']
401
402    def expr_le(self, (obj1, _0, obj2)):
403        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
404            return self.makeconst(obj1.start, obj2.end, obj1.value <= obj2.value)
405        return ul4.LE(obj1.start, obj2.end, obj1, obj2)
406    expr_le.spark = ['expr4 ::= expr4 <= expr4']
407
408    def expr_gt(self, (obj1, _0, obj2)):
409        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
410            return self.makeconst(obj1.start, obj2.end, obj1.value > obj2.value)
411        return ul4.GT(obj1.start, obj2.end, obj1, obj2)
412    expr_gt.spark = ['expr4 ::= expr4 > expr4']
413
414    def expr_ge(self, (obj1, _0, obj2)):
415        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
416            return self.makeconst(obj1.start, obj2.end, obj1.value >= obj2.value)
417        return ul4.GE(obj1.start, obj2.end, obj1, obj2)
418    expr_ge.spark = ['expr4 ::= expr4 >= expr4']
419
420    def expr_contains(self, (obj, _0, container)):
421        if isinstance(obj, ul4.LoadConst) and isinstance(container, ul4.LoadConst): # Constant folding
422            return self.makeconst(obj.start, container.end, obj.value in container.value)
423        return ul4.Contains(obj.start, container.end, obj, container)
424    expr_contains.spark = ['expr3 ::= expr3 in expr3']
425
426    def expr_notcontains(self, (obj, _0, _1, container)):
427        if isinstance(obj, ul4.LoadConst) and isinstance(container, ul4.LoadConst): # Constant folding
428            return self.makeconst(obj.start, container.end, obj.value not in container.value)
429        return ul4.NotContains(obj.start, container.end, obj, container)
430    expr_notcontains.spark = ['expr3 ::= expr3 not in expr3']
431
432    def expr_not(self, (_0, expr)):
433        if isinstance(expr, ul4.LoadConst): # Constant folding
434            return self.makeconst(_0.start, expr.end, not expr.value)
435        return ul4.Not(_0.start, expr.end, expr)
436    expr_not.spark = ['expr2 ::= not expr2']
437
438    def expr_and(self, (obj1, _0, obj2)):
439        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
440            return self.makeconst(obj1.start, obj2.end, bool(obj1.value and obj2.value))
441        return ul4.And(obj1.start, obj2.end, obj1, obj2)
442    expr_and.spark = ['expr1 ::= expr1 and expr1']
443
444    def expr_or(self, (obj1, _0, obj2)):
445        if isinstance(obj1, ul4.LoadConst) and isinstance(obj2, ul4.LoadConst): # Constant folding
446            return self.makeconst(obj1.start, obj2.end, bool(obj1.value or obj2.value))
447        return ul4.Or(obj1.start, obj2.end, obj1, obj2)
448    expr_or.spark = ['expr0 ::= expr0 or expr0']
449
450    # These rules make operators of different precedences interoperable, by allowing an expression to "drop" its precedence.
451    def expr_dropprecedence(self, (expr, )):
452        return expr
453    expr_dropprecedence.spark = [
454        'expr10 ::= expr11',
455        'expr9 ::= expr10',
456        'expr8 ::= expr9',
457        'expr7 ::= expr8',
458        'expr6 ::= expr7',
459        'expr5 ::= expr6',
460        'expr4 ::= expr5',
461        'expr3 ::= expr4',
462        'expr2 ::= expr3',
463        'expr1 ::= expr2',
464        'expr0 ::= expr1',
465    ]
466
467
468class ForParser(ExprParser):
469    emptyerror = "loop expression required"
470
471    def __init__(self, start="for"):
472        ExprParser.__init__(self, start)
473
474    def for0(self, (iter, _0, cont)):
475        return ul4.For(iter.start, cont.end, iter, cont)
476    for0.spark = ['for ::= name in expr0']
477
478    def for1(self, (_0, iter, _1, _2, _3, cont)):
479        return ul4.For1(_0.start, cont.end, iter, cont)
480    for1.spark = ['for ::= ( name , ) in expr0']
481
482    def for2a(self, (_0, iter1, _1, iter2, _2, _3, cont)):
483        return ul4.For2(_0.start, cont.end, iter1, iter2, cont)
484    for2a.spark = ['for ::= ( name , name ) in expr0']
485
486    def for2b(self, (_0, iter1, _1, iter2, _2, _3, _4, cont)):
487        return ul4.For2(_0.start, cont.end, iter1, iter2, cont)
488    for2b.spark = ['for ::= ( name , name , ) in expr0']
489
490    def for3a(self, (_0, iter1, _1, iter2, _2, iter3, _3, _4, cont)):
491        return ul4.For3(_0.start, cont.end, iter1, iter2, iter3, cont)
492    for3a.spark = ['for ::= ( name , name , name ) in expr0']
493
494    def for3b(self, (_0, iter1, _1, iter2, _2, iter3, _3, _4, _5, cont)):
495        return ul4.For3(_0.start, cont.end, iter1, iter2, iter3, cont)
496    for3b.spark = ['for ::= ( name , name , name , ) in expr0']
497
498
499class StmtParser(ExprParser):
500    emptyerror = "statement required"
501
502    def __init__(self, start="stmt"):
503        ExprParser.__init__(self, start)
504
505    def stmt_assign(self, (name, _0, value)):
506        return ul4.StoreVar(name.start, value.end, name, value)
507    stmt_assign.spark = ['stmt ::= name = expr0']
508
509    def stmt_iadd(self, (name, _0, value)):
510        return ul4.AddVar(name.start, value.end, name, value)
511    stmt_iadd.spark = ['stmt ::= name += expr0']
512
513    def stmt_isub(self, (name, _0, value)):
514        return ul4.SubVar(name.start, value.end, name, value)
515    stmt_isub.spark = ['stmt ::= name -= expr0']
516
517    def stmt_imul(self, (name, _0, value)):
518        return ul4.MulVar(name.start, value.end, name, value)
519    stmt_imul.spark = ['stmt ::= name *= expr0']
520
521    def stmt_itruediv(self, (name, _0, value)):
522        return ul4.TrueDivVar(name.start, value.end, name, value)
523    stmt_itruediv.spark = ['stmt ::= name /= expr0']
524
525    def stmt_ifloordiv(self, (name, _0, value)):
526        return ul4.FloorDivVar(name.start, value.end, name, value)
527    stmt_ifloordiv.spark = ['stmt ::= name //= expr0']
528
529    def stmt_imod(self, (name, _0, value)):
530        return ul4.ModVar(name.start, value.end, name, value)
531    stmt_imod.spark = ['stmt ::= name %= expr0']
532
533    def stmt_del(self, (_0, name)):
534        return ul4.DelVar(_0.start, name.end, name)
535    stmt_del.spark = ['stmt ::= del name']
536
537
538class RenderParser(ExprParser):
539    emptyerror = "render statement required"
540
541    def __init__(self, start="render"):
542        ExprParser.__init__(self, start)
543
544    def emptyrender(self, (template, _1, _2)):
545        return ul4.Render(template.start, _2.end, template)
546    emptyrender.spark = ['render ::= expr0 ( )']
547
548    def startrender(self, (template, _1, argname, _2, argexpr)):
549        render = ul4.Render(template.start, argexpr.end, template)
550        render.append(argname.value, argexpr)
551        return render
552    startrender.spark = ['buildrender ::= expr0 ( name = expr0 ']
553
554    def startrenderupdate(self, (template, _0, _1, arg)):
555        render = ul4.Render(template.start, arg.end, template)
556        render.append(arg)
557        return render
558    startrenderupdate.spark = ['buildrender ::= expr0 ( ** expr0']
559
560    def buildrender(self, (render, _1, argname, _2, argexpr)):
561        render.append(argname.value, argexpr)
562        render.end = argexpr.end
563        return render
564    buildrender.spark = ['buildrender ::= buildrender , name = expr0']
565
566    def buildrenderupdate(self, (render, _0, _1, arg)):
567        render.append(arg)
568        render.end = arg.end
569        return render
570    buildrenderupdate.spark = ['buildrender ::= buildrender , ** expr0']
571
572    def finishrender(self, (render, _0)):
573        render.end = _0.end
574        return render
575    finishrender.spark = ['render ::= buildrender )']
576
577    def finishrender1(self, (render, _0, _1)):
578        render.end = _1.end
579        return render
580    finishrender1.spark = ['render ::= buildrender , )']
581
582
583class Compiler(ul4.CompilerType):
584    def compile(self, source, tags, startdelim, enddelim):
585        template = ul4.Template()
586        template.startdelim = startdelim
587        template.enddelim = enddelim
588        template.source = source
589        _compile(template, tags)
590        return template
Note: See TracBrowser for help on using the browser.