| 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} |
| ; |