Note that besides global (ANTLR) scopes, you can also have local rule-scopes, like this:
grammar T;
options { backtrack=true; }
parse
scope { String x; }
parse
: 'foo'? ID {$parse::x = "xyz";} rule*
| 'foo' ID
;
rule
: ID {System.out.println("x=" + $parse::x);}
;
The only time I'd consider using local rule-scopes is when there are a lot of predicates, or global backtracking is enabled (resulting in all rules to have predicates in front of them). In that case, you could create a member variable String x
(or define it in a global scope) and set it in the parse
rule, but you might be changing this instance/scope variable after which the parser could backtrack, and this backtracking will not cause the global variable to be set to it's original form/state! The local scoped variable will also not be "unset", but that will likely be less of a risk: them being local to a single rule.
To summarize: yes, you're right, global scopes and member/instance variables are much alike. But I'd sooner opt for members-variables because of the friendlier syntax.