root/livinglogic.java.ul4/library/Lib/ul4c.py @ 232:ec41feb2068b

Revision 232:ec41feb2068b, 21.8 KB (checked in by Walter Doerwald <walter@…>, 10 years ago)

Fix another bug in the block stack nesting check.

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