aboutsummaryrefslogtreecommitdiff
path: root/runtime/Python/tests/t022scopes.g
blob: 1affc83ea135396f3e38a6574e05db92a2066e12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
grammar t022scopes;

options {
    language=Python;
}

/* global scopes */

scope aScope {
names
}

a
scope aScope;
    :   {$aScope::names = [];} ID*
    ;


/* rule scopes, from the book, final beta, p.147 */

b[v]
scope {x}
    : {$b::x = v;} b2
    ;

b2
    : b3
    ;

b3 
    : {$b::x}?=> ID // only visible, if b was called with True
    | NUM
    ;


/* rule scopes, from the book, final beta, p.148 */

c returns [res]
scope {
    symbols
}
@init {
    $c::symbols = set();
}
    : '{' c1* c2+ '}'
        { $res = $c::symbols; }
    ;

c1
    : 'int' ID {$c::symbols.add($ID.text)} ';'
    ;

c2
    : ID '=' NUM ';'
        {
            if $ID.text not in $c::symbols:
                raise RuntimeError($ID.text)
        }
    ;

/* recursive rule scopes, from the book, final beta, p.150 */

d returns [res]
scope {
    symbols
}
@init {
    $d::symbols = set();
}
    : '{' d1* d2* '}'
        { $res = $d::symbols; }
    ;

d1
    : 'int' ID {$d::symbols.add($ID.text)} ';'
    ;

d2
    : ID '=' NUM ';'
        {
            for s in reversed(range(len($d))):
                if $ID.text in $d[s]::symbols:
                    break
            else:
                raise RuntimeError($ID.text)
        }
    | d
    ;

/* recursive rule scopes, access bottom-most scope */

e returns [res]
scope {
    a
}
@after {
    $res = $e::a;
}
    : NUM { $e[0]::a = int($NUM.text); }
    | '{' e '}'
    ;


/* recursive rule scopes, access with negative index */

f returns [res]
scope {
    a
}
@after {
    $res = $f::a;
}
    : NUM { $f[-2]::a = int($NUM.text); }
    | '{' f '}'
    ;


/* tokens */

ID  :   ('a'..'z')+
    ;

NUM :   ('0'..'9')+
    ;

WS  :   (' '|'\n'|'\r')+ {$channel=HIDDEN}
    ;