root/livinglogic.python.xist/src/ll/UL4.g @ 5336:fe802c9b09e9

Revision 5336:fe802c9b09e9, 10.5 KB (checked in by Walter Doerwald <walter@…>, 7 years ago)

Merge AST and Tag again.

Expressions are now allowed as the content of <?code tag?>, so they may sit at
the top level in tags.

Have the location object point back to the root template. With this we don't
have to pass along the keepws flag in eval().

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(self.location, None) }
144    ;
145
146true_ returns [node]
147    : TRUE { $node = ul4c.Const(self.location, True) }
148    ;
149
150false_ returns [node]
151    : FALSE { $node = ul4c.Const(self.location, False) }
152    ;
153
154int_ returns [node]
155    : INT { $node = ul4c.Const(self.location, int($INT.text, 0)) }
156    ;
157
158float_ returns [node]
159    : FLOAT { $node = ul4c.Const(self.location, float($FLOAT.text)) }
160    ;
161
162string returns [node]
163    : STRING { $node = ul4c.Const(self.location, ast.literal_eval($STRING.text)) }
164    ;
165
166date returns [node]
167    : DATE { $node = ul4c.Const(self.location, 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(self.location, color.Color.fromrepr($COLOR.text)) }
172    ;
173
174name returns [node]
175    : NAME { $node = ul4c.Var(self.location, $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(self.location) }
195    |
196        '[' {$node = ul4c.List(self.location) }
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(self.location, $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
234dict returns [node]
235    :
236        '{'
237        '}' { $node = ul4c.Dict(self.location) }
238    |
239        '{' { $node = ul4c.Dict(self.location) }
240        i1=dictitem { $node.items.append($i1.node) }
241        (
242            ','
243            i2=dictitem { $node.items.append($i2.node) }
244        )*
245        ','?
246        '}'
247    ;
248
249dictcomprehension returns [node]
250    @init
251    {
252        _condition = None;
253    }
254    :
255        '{'
256        key=expr1
257        ':'
258        value=expr1
259        'for'
260        n=nestedname
261        'in'
262        container=expr1
263        (
264            'if'
265            condition=expr1 { _condition = $condition.node; }
266        )?
267        '}' { $node = ul4c.DictComp(self.location, $key.node, $value.node, $n.varname, $container.node, _condition) }
268    ;
269
270generatorexpression returns [node]
271    @init
272    {
273        _condition = None;
274    }
275    :
276        item=expr1
277        'for'
278        n=nestedname
279        'in'
280        container=expr1
281        (
282            'if'
283            condition=expr1 { _condition = $condition.node; }
284        )? { $node = ul4c.GenExpr(self.location, $item.node, $n.varname, $container.node, _condition) }
285    ;
286
287atom returns [node]
288    : e_literal=literal { $node = $e_literal.node; }
289    | e_list=list { $node = $e_list.node; }
290    | e_listcomp=listcomprehension { $node = $e_listcomp.node; }
291    | e_dict=dict { $node = $e_dict.node; }
292    | e_dictcomp=dictcomprehension { $node = $e_dictcomp.node; }
293    | '(' e_genexpr=generatorexpression ')' { $node = $e_genexpr.node; }
294    | '(' e_bracket=expr1 ')' { $node = $e_bracket.node; }
295    ;
296
297/* For variable unpacking in assignments and for loops */
298nestedname returns [varname]
299    :
300        n=name { $varname = $n.text; }
301    |
302        '(' n0=nestedname ',' ')' { $varname = ($n0.varname,) }
303    |
304        '('
305        n1=nestedname
306        ','
307        n2=nestedname { $varname = ($n1.varname, $n2.varname) }
308        (
309            ','
310            n3=nestedname { $varname += ($n3.varname,) }
311        )*
312        ','?
313        ')'
314    ;
315
316/* Function/method call, attribute access, item access, slice access */
317expr9 returns [node]
318    @init
319    {
320        callmeth = False
321        index1 = None
322        index2 = None
323        slice = False
324    }
325    :
326        e1=atom { $node = $e1.node; }
327        (
328            /* Attribute access */
329            '.'
330            n=name { $node = ul4c.GetAttr(self.location, $node, $n.text) }
331        |
332            /* Function/method call */
333            '(' { $node = ul4c.CallMeth(self.location, $node.obj, $node.attrname) if isinstance($node, ul4c.GetAttr) else ul4c.CallFunc(self.location, $node) }
334            (
335                /* No arguments */
336            |
337                /* "**" argument only */
338                '**' rkwargs=exprarg { $node.remkwargs = $rkwargs.node; }
339                ','?
340            |
341                /* "*" argument only (and maybe **) */
342                '*' rargs=exprarg { $node.remargs = $rargs.node; }
343                (
344                    ','
345                    '**' rkwargs=exprarg { $node.remkwargs = $rkwargs.node; }
346                )?
347                ','?
348            |
349                /* At least one positional argument */
350                a1=exprarg { $node.args.append($a1.node) }
351                (
352                    ','
353                    a2=exprarg { $node.args.append($a2.node) }
354                )*
355                (
356                    ','
357                    an3=name '=' av3=exprarg { $node.kwargs.append(($an3.text, $av3.node)) }
358                )*
359                (
360                    ','
361                    '*' rargs=exprarg { $node.remargs = $rargs.node; }
362                )?
363                (
364                    ','
365                    '**' rkwargs=exprarg { $node.remkwargs = $rkwargs.node; }
366                )?
367                ','?
368            |
369                /* Keyword arguments only */
370                an1=name '=' av1=exprarg { $node.kwargs.append(($an1.text, $av1.node)) }
371                (
372                    ','
373                    an2=name '=' av2=exprarg { $node.kwargs.append(($an2.text, $av2.node)) }
374                )*
375                (
376                    ','
377                    '*' rargs=exprarg { $node.remargs = $rargs.node; }
378                )?
379                (
380                    ','
381                    '**' rkwargs=exprarg { $node.remkwargs = $rkwargs.node; }
382                )?
383                ','?
384            )
385            ')'
386        |
387            /* Item/slice access */
388            '['
389            (
390                ':'
391                (
392                    e2=expr1 { index2 = $e2.node; }
393                )? { $node = ul4c.GetSlice(self.location, $node, None, index2) }
394            |
395                e2=expr1 { index1 = $e2.node; }
396                (
397                    ':' { slice = True; }
398                    (
399                        e3=expr1 { index2 = $e3.node; }
400                    )?
401                )? { $node = ul4c.GetSlice(self.location, $node, index1, index2) if slice else ul4c.GetItem(self.location, $node, index1) }
402            )
403            ']'
404        )*
405    ;
406
407/* Negation */
408expr8 returns [node]
409    @init
410    {
411        count = 0;
412    }
413    :
414        (
415            '-' { count += 1; }
416        )*
417        e=expr9 {
418            $node = $e.node;
419            for i in range(count):
420                $node = ul4c.Neg.make(self.location, $node);
421        }
422    ;
423
424/* Multiplication, division, modulo */
425expr7 returns [node]
426    :
427        e1=expr8 { $node = $e1.node; }
428        (
429            (
430                '*' { cls = ul4c.Mul; }
431            |
432                '/' { cls = ul4c.TrueDiv; }
433            |
434                '//' { cls = ul4c.FloorDiv; }
435            |
436                '%' { cls = ul4c.Mod; }
437            )
438            e2=expr8 { $node = cls.make(self.location, $node, $e2.node) }
439        )*
440    ;
441
442/* Addition, substraction */
443expr6 returns [node]
444    :
445        e1=expr7 { $node = $e1.node; }
446        (
447            (
448                '+' { cls = ul4c.Add; }
449            |
450                '-' { cls = ul4c.Sub; }
451            )
452            e2=expr7 { $node = cls.make(self.location, $node, $e2.node) }
453        )*
454    ;
455
456/* Comparisons */
457expr5 returns [node]
458    :
459        e1=expr6 { $node = $e1.node; }
460        (
461            (
462                '==' { cls = ul4c.EQ; }
463            |
464                '!=' { cls = ul4c.NE; }
465            |
466                '<' { cls = ul4c.LT; }
467            |
468                '<=' { cls = ul4c.LE; }
469            |
470                '>' { cls = ul4c.GT; }
471            |
472                '>=' { cls = ul4c.GE; }
473            )
474            e2=expr6 { $node = cls.make(self.location, $node, $e2.node) }
475        )*
476    ;
477
478/* "in"/"not in" operator */
479expr4 returns [node]
480    :
481        e1=expr5 { $node = $e1.node; }
482        (
483            { cls = ul4c.Contains; }
484            (
485                'not' { cls = ul4c.NotContains; }
486            )?
487            'in'
488            e2=expr5 { $node = cls.make(self.location, $node, $e2.node) }
489        )?
490    ;
491
492/* Not operator */
493expr3 returns [node]
494    :
495        'not'
496        e=expr4 { $node = ul4c.Not.make(self.location, $e.node) }
497    |
498        e=expr4 { $node = $e.node; }
499    ;
500
501
502/* And operator */
503expr2 returns [node]
504    :
505        e1=expr3 { $node = $e1.node; }
506        (
507            'and'
508            e2=expr3 { $node = ul4c.And(self.location, $node, $e2.node) }
509        )*
510    ;
511
512/* Or operator */
513expr1 returns [node]
514    :
515        e1=expr2 { $node = $e1.node; }
516        (
517            'or'
518            e2=expr2 { $node = ul4c.Or(self.location, $node, $e2.node) }
519        )*
520    ;
521
522exprarg returns [node]
523    : ege=generatorexpression { $node = $ege.node; }
524    | e1=expr1 { $node = $e1.node; }
525    ;
526
527expression returns [node]
528    : ege=generatorexpression EOF { $node = $ege.node; }
529    | e=expr1 EOF { $node = $e.node; }
530    ;
531
532
533/* Additional rules for "for" tag */
534
535for_ returns [node]
536    :
537        n=nestedname
538        'in'
539        e=expr1 { $node = ul4c.For(self.location, $n.varname, $e.node) }
540        EOF
541    ;
542
543
544/* Additional rules for "code" tag */
545
546statement returns [node]
547    : nn=nestedname '=' e=expr1 EOF { $node = ul4c.StoreVar(self.location, $nn.varname, $e.node) }
548    | n=name '+=' e=expr1 EOF { $node = ul4c.AddVar(self.location, $n.text, $e.node) }
549    | n=name '-=' e=expr1 EOF { $node = ul4c.SubVar(self.location, $n.text, $e.node) }
550    | n=name '*=' e=expr1 EOF { $node = ul4c.MulVar(self.location, $n.text, $e.node) }
551    | n=name '/=' e=expr1 EOF { $node = ul4c.TrueDivVar(self.location, $n.text, $e.node) }
552    | n=name '//=' e=expr1 EOF { $node = ul4c.FloorDivVar(self.location, $n.text, $e.node) }
553    | n=name '%=' e=expr1 EOF { $node = ul4c.ModVar(self.location, $n.text, $e.node) }
554    | e=expression EOF { $node = $e.node }
555    ;
Note: See TracBrowser for help on using the browser.