grammar SymbolTable;

/* Scope of symbol names.  Both globals and block rules need to push a new
 * symbol table upon entry and they must use the same stack.  So, I must
 * define a global scope and say that globals and block use this by saying
 * 'scope Symbols;' in those rule definitions.
 */

options {
	language=ObjC;
}

scope Symbols {
  PtrBuffer *names;
}

@memVars {
int level;
}

@init {
level = 0;
}

prog
// scope Symbols;
    :   globals (method)*
    ;

globals
scope Symbols;
@init {
    level++;
    $Symbols::names = [PtrBuffer newPtrBufferWithLen:10];
}
    :   (decl)*
        {
            NSLog( @"globals: \%@", [$Symbols::names toString] );
            level--;
        }
    ;

method
    :   'method' ID '(' ')' block
    ;

block
scope Symbols;
@init {
    level++;
    $Symbols::names = [PtrBuffer newPtrBufferWithLen:10];
}
    :   '{' (decl)* (stat)* '}'
        {
            NSLog( @"level \%d symbols: \%@", level, [$Symbols::names toString] );
            level--;
        }
    ;

stat:   ID '=' INT ';'
    |   block
    ;

decl:   'int' ID ';'
        {[$Symbols::names addObject:$ID];} // add to current symbol table
    ;

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

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

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