root/livinglogic.python.xist/src/ll/UL4.g @ 5312:9a98178e4483

Revision 5312:9a98178e4483, 10.1 KB (checked in by Walter Doerwald <walter@…>, 7 years ago)

Merge UL4 templates and functions again.

Templates call be called as functions. All ouput will be ignored in this case.

Executing templates is now done by interpreting the AST directly (via the eval()
method), instead of generating Python source code from it first.

AST nodes can both produce output and return results via enhanced generators.

Constant folding has been removed.

Line 
1grammar UL4;
2
3options
4{
5    language=Python;
6    backtrack=true;
7}
8
9@lexer::header
10{
11    from ll import ul4c
12}
13
14@header
15{
16    import datetime, ast
17    from ll import ul4c, color
18}
19
20@lexer::members {
21def reportError(self, e):
22   raise e
23}
24
25@members {
26def mismatch(self, input, ttype, follow):
27    raise MismatchedTokenException(ttype, input)
28
29def recoverFromMismatchedSet(self, input, e, follow):
30    raise e
31}
32
33@rulecatch {
34except RecognitionException as e:
35    raise
36}
37
38NONE
39    : 'None'
40    ;
41
42TRUE
43    : 'True'
44    ;
45
46FALSE
47    : 'False'
48    ;
49
50NAME
51    : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
52    ;
53
54fragment
55DIGIT
56    : '0'..'9'
57    ;
58
59fragment
60BIN_DIGIT
61    : ('0'|'1')
62    ;
63
64fragment
65OCT_DIGIT
66    : '0'..'7'
67    ;
68
69fragment
70HEX_DIGIT
71    : ('0'..'9'|'a'..'f'|'A'..'F')
72    ;
73
74/* We don't have negative ints (as this would lex "1-2" wrong) */
75INT
76    : DIGIT+
77    | '0' ('b'|'B') BIN_DIGIT+
78    | '0' ('o'|'O') OCT_DIGIT+
79    | '0' ('x'|'X') HEX_DIGIT+
80    ;
81
82fragment
83EXPONENT
84    : ('e'|'E') ('+'|'-')? DIGIT+
85    ;
86
87FLOAT
88    : DIGIT+ '.' DIGIT* EXPONENT?
89    | '.' DIGIT+ EXPONENT?
90    | DIGIT+ EXPONENT
91    ;
92
93fragment
94TIME
95    : DIGIT DIGIT ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT DIGIT DIGIT DIGIT)?)?;
96
97DATE
98    : '@' '(' DIGIT DIGIT DIGIT DIGIT '-' DIGIT DIGIT '-' DIGIT DIGIT ('T' TIME?)? ')';
99
100COLOR
101    : '#' HEX_DIGIT HEX_DIGIT HEX_DIGIT
102    | '#' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
103    | '#' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
104    | '#' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
105    ;
106
107WS
108    : (' '|'\t'|'\r'|'\n') { $channel=HIDDEN; }
109    ;
110
111STRING
112    : '"' ( ESC_SEQ | ~('\\'|'"'|'\r'|'\n') )* '"'
113    | '\'' ( ESC_SEQ | ~('\\'|'\''|'\r'|'\n') )* '\''
114    ;
115
116fragment
117ESC_SEQ
118    : '\\' ('a'|'b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
119    | UNICODE1_ESC
120    | UNICODE2_ESC
121    | UNICODE4_ESC
122    ;
123
124fragment
125UNICODE1_ESC
126    : '\\' 'x' HEX_DIGIT HEX_DIGIT
127    ;
128
129fragment
130UNICODE2_ESC
131    : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
132    ;
133
134fragment
135UNICODE4_ESC
136    : '\\' 'U' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
137    ;
138
139
140/* Rules common to all tags */
141
142none returns [node]
143    : NONE { $node = ul4c.Const(None); }
144    ;
145
146true_ returns [node]
147    : TRUE { $node = ul4c.Const(True); }
148    ;
149
150false_ returns [node]
151    : FALSE { $node = ul4c.Const(False); }
152    ;
153
154int_ returns [node]
155    : INT { $node = ul4c.Const(int($INT.text, 0)); }
156    ;
157
158float_ returns [node]
159    : FLOAT { $node = ul4c.Const(float($FLOAT.text)); }
160    ;
161
162string returns [node]
163    : STRING { $node = ul4c.Const(ast.literal_eval($STRING.text)); }
164    ;
165
166date returns [node]
167    : DATE { $node = ul4c.Const(datetime.datetime(*map(int, [f for f in ul4c.datesplitter.split($DATE.text[2:-1]) if f]))); }
168    ;
169
170color returns [node]
171    : COLOR { $node = ul4c.Const(color.Color.fromrepr($COLOR.text)); }
172    ;
173
174name returns [node]
175    : NAME { $node = ul4c.Var($NAME.text); }
176    ;
177
178literal returns [node]
179    : e_none=none { $node = $e_none.node; }
180    | e_false=false_ { $node = $e_false.node; }
181    | e_true=true_ { $node = $e_true.node; }
182    | e_int=int_ { $node = $e_int.node; }
183    | e_float=float_ { $node = $e_float.node; }
184    | e_string=string { $node = $e_string.node; }
185    | e_date=date { $node = $e_date.node; }
186    | e_color=color { $node = $e_color.node; }
187    | e_name=name { $node = $e_name.node; }
188    ;
189
190/* List literals */
191list returns [node]
192    :
193        '['
194        ']' { $node = ul4c.List(); }
195    |
196        '[' {$node = ul4c.List(); }
197        e1=expr1 { $node.items.append($e1.node); }
198        (
199            ','
200            e2=expr1 { $node.items.append($e2.node); }
201        )*
202        ','?
203        ']'
204    ;
205
206listcomprehension returns [node]
207    @init
208    {
209        _condition = None;
210    }
211    :
212        '['
213        item=expr1
214        'for'
215        n=nestedname
216        'in'
217        container=expr1
218        (
219            'if'
220            condition=expr1 { _condition = $condition.node; }
221        )?
222        ']' { $node = ul4c.ListComp($item.node, $n.varname, $container.node, _condition); }
223    ;
224
225/* Dict literal */
226fragment
227dictitem returns [node]
228    :
229        k=expr1
230        ':'
231        v=expr1 { $node = ($k.node, $v.node); }
232    |
233        '**'
234        d=expr1 { $node = ($d.node,); }
235    ;
236
237dict returns [node]
238    :
239        '{'
240        '}' { $node = ul4c.Dict(); }
241    |
242        '{' { $node = ul4c.Dict(); }
243        i1=dictitem { $node.items.append($i1.node); }
244        (
245            ','
246            i2=dictitem { $node.items.append($i2.node); }
247        )*
248        ','?
249        '}'
250    ;
251
252dictcomprehension returns [node]
253    @init
254    {
255        _condition = None;
256    }
257    :
258        '{'
259        key=expr1
260        ':'
261        value=expr1
262        'for'
263        n=nestedname
264        'in'
265        container=expr1
266        (
267            'if'
268            condition=expr1 { _condition = $condition.node; }
269        )?
270        '}' { $node = ul4c.DictComp($key.node, $value.node, $n.varname, $container.node, _condition); }
271    ;
272
273generatorexpression returns [node]
274    @init
275    {
276        _condition = None;
277    }
278    :
279        item=expr1
280        'for'
281        n=nestedname
282        'in'
283        container=expr1
284        (
285            'if'
286            condition=expr1 { _condition = $condition.node; }
287        )? { $node = ul4c.GenExpr($item.node, $n.varname, $container.node, _condition); }
288    ;
289
290atom returns [node]
291    : e_literal=literal { $node = $e_literal.node; }
292    | e_list=list { $node = $e_list.node; }
293    | e_listcomp=listcomprehension { $node = $e_listcomp.node; }
294    | e_dict=dict { $node = $e_dict.node; }
295    | e_dictcomp=dictcomprehension { $node = $e_dictcomp.node; }
296    | '(' e_genexpr=generatorexpression ')' { $node = $e_genexpr.node; }
297    | '(' e_bracket=expr1 ')' { $node = $e_bracket.node; }
298    ;
299
300/* For variable unpacking in assignments and for loops */
301nestedname returns [varname]
302    :
303        n=name { $varname = $n.text; }
304    |
305        '(' n0=nestedname ',' ')' { $varname = ($n0.varname,); }
306    |
307        '('
308        n1=nestedname
309        ','
310        n2=nestedname { $varname = ($n1.varname, $n2.varname); }
311        (
312            ','
313            n3=nestedname { $varname += ($n3.varname,); }
314        )*
315        ','?
316        ')'
317    ;
318
319/* Function/method call, attribute access, item access, slice access */
320expr9 returns [node]
321    @init
322    {
323        callmeth = False
324        index1 = None
325        index2 = None
326        slice = False
327    }
328    :
329        e1=atom { $node = $e1.node; }
330        (
331            /* Attribute access */
332            '.'
333            n=name { $node = ul4c.GetAttr($node, $n.text); }
334        |
335            /* Function/method call */
336            '(' { $node = ul4c.CallMeth($node.obj, $node.attrname) if isinstance($node, ul4c.GetAttr) else ul4c.CallFunc($node); }
337            (
338                /* No arguments */
339            |
340                /* "**" argument only */
341                '**' rkwargs=exprarg { $node.remkwargs = $rkwargs.node; }
342                ','?
343            |
344                /* "*" argument only (and maybe **) */
345                '*' rargs=exprarg { $node.remargs = $rargs.node; }
346                (
347                    ','
348                    '**' rkwargs=exprarg { $node.remkwargs = $rkwargs.node; }
349                )?
350                ','?
351            |
352                /* At least one positional argument */
353                a1=exprarg { $node.args.append($a1.node); }
354                (
355                    ','
356                    a2=exprarg { $node.args.append($a2.node); }
357                )*
358                (
359                    ','
360                    an3=name '=' av3=exprarg { $node.kwargs.append(($an3.text, $av3.node)); }
361                )*
362                (
363                    ','
364                    '*' rargs=exprarg { $node.remargs = $rargs.node; }
365                )?
366                (
367                    ','
368                    '**' rkwargs=exprarg { $node.remkwargs = $rkwargs.node; }
369                )?
370                ','?
371            |
372                /* Keyword arguments only */
373                an1=name '=' av1=exprarg { $node.kwargs.append(($an1.text, $av1.node)); }
374                (
375                    ','
376                    an2=name '=' av2=exprarg { $node.kwargs.append(($an2.text, $av2.node)); }
377                )*
378                (
379                    ','
380                    '*' rargs=exprarg { $node.remargs = $rargs.node; }
381                )?
382                (
383                    ','
384                    '**' rkwargs=exprarg { $node.remkwargs = $rkwargs.node; }
385                )?
386                ','?
387            )
388            ')'
389        |
390            /* Item/slice access */
391            '['
392            (
393                ':'
394                (
395                    e2=expr1 { index2 = $e2.node; }
396                )? { $node = ul4c.GetSlice($node, None, index2); }
397            |
398                e2=expr1 { index1 = $e2.node; }
399                (
400                    ':' { slice = True; }
401                    (
402                        e3=expr1 { index2 = $e3.node; }
403                    )?
404                )? { $node = ul4c.GetSlice($node, index1, index2) if slice else ul4c.GetItem($node, index1); }
405            )
406            ']'
407        )*
408    ;
409
410/* Negation */
411expr8 returns [node]
412    @init
413    {
414        count = 0;
415    }
416    :
417        (
418            '-' { count += 1; }
419        )*
420        e=expr9 {
421            $node = $e.node;
422            for i in range(count):
423                $node = ul4c.Neg($node);
424        }
425    ;
426
427/* Multiplication, division, modulo */
428expr7 returns [node]
429    :
430        e1=expr8 { $node = $e1.node; }
431        (
432            (
433                '*' { cls = ul4c.Mul; }
434            |
435                '/' { cls = ul4c.TrueDiv; }
436            |
437                '//' { cls = ul4c.FloorDiv; }
438            |
439                '%' { cls = ul4c.Mod; }
440            )
441            e2=expr8 { $node = cls($node, $e2.node); }
442        )*
443    ;
444
445/* Addition, substraction */
446expr6 returns [node]
447    :
448        e1=expr7 { $node = $e1.node; }
449        (
450            (
451                '+' { cls = ul4c.Add; }
452            |
453                '-' { cls = ul4c.Sub; }
454            )
455            e2=expr7 { $node = cls($node, $e2.node) }
456        )*
457    ;
458
459/* Comparisons */
460expr5 returns [node]
461    :
462        e1=expr6 { $node = $e1.node; }
463        (
464            (
465                '==' { cls = ul4c.EQ; }
466            |
467                '!=' { cls = ul4c.NE; }
468            |
469                '<' { cls = ul4c.LT; }
470            |
471                '<=' { cls = ul4c.LE; }
472            |
473                '>' { cls = ul4c.GT; }
474            |
475                '>=' { cls = ul4c.GE; }
476            )
477            e2=expr6 { $node = cls($node, $e2.node); }
478        )*
479    ;
480
481/* "in"/"not in" operator */
482expr4 returns [node]
483    :
484        e1=expr5 { $node = $e1.node; }
485        (
486            { cls = ul4c.Contains; }
487            (
488                'not' { cls = ul4c.NotContains; }
489            )?
490            'in'
491            e2=expr5 { $node = cls($node, $e2.node); }
492        )?
493    ;
494
495/* Not operator */
496expr3 returns [node]
497    :
498        'not'
499        e=expr4 { $node = ul4c.Not($e.node); }
500    |
501        e=expr4 { $node = $e.node; }
502    ;
503
504
505/* And operator */
506expr2 returns [node]
507    :
508        e1=expr3 { $node = $e1.node; }
509        (
510            'and'
511            e2=expr3 { $node = ul4c.And($node, $e2.node); }
512        )*
513    ;
514
515/* Or operator */
516expr1 returns [node]
517    :
518        e1=expr2 { $node = $e1.node; }
519        (
520            'or'
521            e2=expr2 { $node = ul4c.Or($node, $e2.node); }
522        )*
523    ;
524
525exprarg returns [node]
526    : ege=generatorexpression { $node = $ege.node; }
527    | e1=expr1 { $node = $e1.node; }
528    ;
529
530expression returns [node]
531    : ege=generatorexpression EOF { $node = $ege.node; }
532    | e=expr1 EOF { $node = $e.node; }
533    ;
534
535
536/* Additional rules for "for" tag */
537
538for_ returns [node]
539    :
540        n=nestedname
541        'in'
542        e=expr1 { $node = ul4c.For(self.location, $n.varname, $e.node); }
543        EOF
544    ;
545
546
547/* Additional rules for "code" tag */
548
549statement returns [node]
550    : nn=nestedname '=' e=expr1 EOF { $node = ul4c.StoreVar(self.location, $nn.varname, $e.node); }
551    | n=name '+=' e=expr1 EOF { $node = ul4c.AddVar(self.location, $n.text, $e.node); }
552    | n=name '-=' e=expr1 EOF { $node = ul4c.SubVar(self.location, $n.text, $e.node); }
553    | n=name '*=' e=expr1 EOF { $node = ul4c.MulVar(self.location, $n.text, $e.node); }
554    | n=name '/=' e=expr1 EOF { $node = ul4c.TrueDivVar(self.location, $n.text, $e.node); }
555    | n=name '//=' e=expr1 EOF { $node = ul4c.FloorDivVar(self.location, $n.text, $e.node); }
556    | n=name '%=' e=expr1 EOF { $node = ul4c.ModVar(self.location, $n.text, $e.node); }
557    ;
Note: See TracBrowser for help on using the browser.