root/livinglogic.python.xist/src/ll/UL4.g @ 5347:da430915bf69

Revision 5347:da430915bf69, 12.2 KB (checked in by Walter Doerwald <walter@…>, 7 years ago)

Store source code start/end offsets for all AST nodes.

This simplifies str output of most nodes, as they can simply output the
appropriate slice of the original source code.

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