root/livinglogic.java.ul4/library/src/com/livinglogic/ul4/ul4c.py @ 147:749677aebf7e

Revision 147:749677aebf7e, 18.6 KB (checked in by Alexander Lamm <alexander.lamm@…>, 11 years ago)

Drop rule for slice copy.

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