Home | History | Annotate | Download | only in functional
      1 grammar t022scopes;
      2 
      3 options {
      4     language=JavaScript;
      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 = {};
     44 }
     45     : '{' c1* c2+ '}'
     46         { $res = $c::symbols; }
     47     ;
     48 
     49 c1
     50     : 'int' ID {$c::symbols[$ID.text] = true;} ';'
     51     ;
     52 
     53 c2
     54     : ID '=' NUM ';'
     55         {
     56             if (! $c::symbols[$ID.text]) {
     57                 throw new Error($ID.text);
     58             }
     59         }
     60     ;
     61 
     62 /* recursive rule scopes, from the book, final beta, p.150 */
     63 
     64 d returns [res]
     65 scope {
     66     symbols
     67 }
     68 @init {
     69     $d::symbols = {};
     70 }
     71     : '{' d1* d2* '}'
     72         { $res = $d::symbols; }
     73     ;
     74 
     75 d1
     76     : 'int' ID {$d::symbols[$ID.text] = true;} ';'
     77     ;
     78 
     79 d2
     80     : ID '=' NUM ';'
     81         {
     82             var i, isDefined;
     83             for (i=$d.length-1, isDefined=false; i>=0; i--) {
     84                 if ($d[i]::symbols[$ID.text]) {
     85                     isDefined = true;
     86                     break;
     87                 }
     88             }
     89             if (!isDefined) {
     90                 throw new Error("undefined variable "+$ID.text);
     91             }
     92         }
     93     | d
     94     ;
     95 
     96 /* recursive rule scopes, access bottom-most scope */
     97 
     98 e returns [res]
     99 scope {
    100     a
    101 }
    102 @after {
    103     $res = $e::a;
    104 }
    105     : NUM { $e[0]::a = parseInt($NUM.text, 10); }
    106     | '{' e '}'
    107     ;
    108 
    109 
    110 /* recursive rule scopes, access with negative index */
    111 
    112 f returns [res]
    113 scope {
    114     a
    115 }
    116 @after {
    117     $res = $f::a;
    118 }
    119     : NUM { var len = $f.length-2; $f[len>=0 ? len : 0]::a = parseInt($NUM.text, 10); }
    120     | '{' f '}'
    121     ;
    122 
    123 
    124 /* tokens */
    125 ID  :   ('a'..'z')+
    126     ;
    127 
    128 NUM :   ('0'..'9')+
    129     ;
    130 
    131 WS  :   (' '|'\n'|'\r')+ {$channel=HIDDEN;}
    132     ;
    133