1grammar t022scopes;
2
3options {
4    language=Python;
5}
6
7/* global scopes */
8
9scope aScope {
10names
11}
12
13a
14scope aScope;
15    :   {$aScope::names = [];} ID*
16    ;
17
18
19/* rule scopes, from the book, final beta, p.147 */
20
21b[v]
22scope {x}
23    : {$b::x = v;} b2
24    ;
25
26b2
27    : b3
28    ;
29
30b3
31    : {$b::x}?=> ID // only visible, if b was called with True
32    | NUM
33    ;
34
35
36/* rule scopes, from the book, final beta, p.148 */
37
38c returns [res]
39scope {
40    symbols
41}
42@init {
43    $c::symbols = set();
44}
45    : '{' c1* c2+ '}'
46        { $res = $c::symbols; }
47    ;
48
49c1
50    : 'int' ID {$c::symbols.add($ID.text)} ';'
51    ;
52
53c2
54    : ID '=' NUM ';'
55        {
56            if $ID.text not in $c::symbols:
57                raise RuntimeError($ID.text)
58        }
59    ;
60
61/* recursive rule scopes, from the book, final beta, p.150 */
62
63d returns [res]
64scope {
65    symbols
66}
67@init {
68    $d::symbols = set();
69}
70    : '{' d1* d2* '}'
71        { $res = $d::symbols; }
72    ;
73
74d1
75    : 'int' ID {$d::symbols.add($ID.text)} ';'
76    ;
77
78d2
79    : ID '=' NUM ';'
80        {
81            for s in reversed(range(len($d))):
82                if $ID.text in $d[s]::symbols:
83                    break
84            else:
85                raise RuntimeError($ID.text)
86        }
87    | d
88    ;
89
90/* recursive rule scopes, access bottom-most scope */
91
92e returns [res]
93scope {
94    a
95}
96@after {
97    $res = $e::a;
98}
99    : NUM { $e[0]::a = int($NUM.text); }
100    | '{' e '}'
101    ;
102
103
104/* recursive rule scopes, access with negative index */
105
106f returns [res]
107scope {
108    a
109}
110@after {
111    $res = $f::a;
112}
113    : NUM { $f[-2]::a = int($NUM.text); }
114    | '{' f '}'
115    ;
116
117
118/* tokens */
119
120ID  :   ('a'..'z')+
121    ;
122
123NUM :   ('0'..'9')+
124    ;
125
126WS  :   (' '|'\n'|'\r')+ {$channel=HIDDEN}
127    ;
128