1grammar SymbolTable; 2 3/* Scope of symbol names. Both globals and block rules need to push a new 4 * symbol table upon entry and they must use the same stack. So, I must 5 * define a global scope and say that globals and block use this by saying 6 * 'scope Symbols;' in those rule definitions. 7 */ 8 9options { 10 language=ObjC; 11} 12 13scope Symbols { 14 PtrBuffer *names; 15} 16 17@memVars { 18int level; 19} 20 21@init { 22level = 0; 23} 24 25prog 26// scope Symbols; 27 : globals (method)* 28 ; 29 30globals 31scope Symbols; 32@init { 33 level++; 34 $Symbols::names = [PtrBuffer newPtrBufferWithLen:10]; 35} 36 : (decl)* 37 { 38 NSLog( @"globals: \%@", [$Symbols::names toString] ); 39 level--; 40 } 41 ; 42 43method 44 : 'method' ID '(' ')' block 45 ; 46 47block 48scope Symbols; 49@init { 50 level++; 51 $Symbols::names = [PtrBuffer newPtrBufferWithLen:10]; 52} 53 : '{' (decl)* (stat)* '}' 54 { 55 NSLog( @"level \%d symbols: \%@", level, [$Symbols::names toString] ); 56 level--; 57 } 58 ; 59 60stat: ID '=' INT ';' 61 | block 62 ; 63 64decl: 'int' ID ';' 65 {[$Symbols::names addObject:$ID];} // add to current symbol table 66 ; 67 68ID : ('a'..'z')+ 69 ; 70 71INT : ('0'..'9')+ 72 ; 73 74WS : (' '|'\n'|'\r')+ {$channel=HIDDEN;} 75 ; 76