root/livinglogic.java.ul4/src/main/antlr3/com/livinglogic/ul4/UL4.g @ 784:2d4c0496f17f

Revision 784:2d4c0496f17f, 11.8 KB (checked in by Walter Doerwald <walter@…>, 7 years ago)

Implement UL4 functions. Remove vars(), get(), CompiledTemplate?, Java/JS conversion.

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