1 grammar t022scopes; 2 3 options { 4 language=Python; 5 } 6 7 /* global scopes */ 8 9 scope aScope { 10 names 11 } 12 13 a 14 scope aScope; 15 : {$aScope::names = [];} ID* 16 ; 17 18 19 /* rule scopes, from the book, final beta, p.147 */ 20 21 b[v] 22 scope {x} 23 : {$b::x = v;} b2 24 ; 25 26 b2 27 : b3 28 ; 29 30 b3 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 38 c returns [res] 39 scope { 40 symbols 41 } 42 @init { 43 $c::symbols = set(); 44 } 45 : '{' c1* c2+ '}' 46 { $res = $c::symbols; } 47 ; 48 49 c1 50 : 'int' ID {$c::symbols.add($ID.text)} ';' 51 ; 52 53 c2 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 63 d returns [res] 64 scope { 65 symbols 66 } 67 @init { 68 $d::symbols = set(); 69 } 70 : '{' d1* d2* '}' 71 { $res = $d::symbols; } 72 ; 73 74 d1 75 : 'int' ID {$d::symbols.add($ID.text)} ';' 76 ; 77 78 d2 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 92 e returns [res] 93 scope { 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 106 f returns [res] 107 scope { 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 120 ID : ('a'..'z')+ 121 ; 122 123 NUM : ('0'..'9')+ 124 ; 125 126 WS : (' '|'\n'|'\r')+ {$channel=HIDDEN} 127 ; 128