boolean checkElementOptions(GrammarASTWithOptions elem,
								GrammarAST ID,
								GrammarAST valueAST)
	{
		if (checkAssocElementOption && ID != null && "assoc".equals(ID.getText())) {
			if (elem.getType() != ANTLRParser.ALT) {
				Token optionID = ID.token;
				String fileName = optionID.getInputStream().getSourceName();
				g.tool.errMgr.grammarError(ErrorType.UNRECOGNIZED_ASSOC_OPTION,
										   fileName,
										   optionID,
										   currentRuleName);
			}
		}

		if ( elem instanceof RuleRefAST ) {
			return checkRuleRefOptions((RuleRefAST)elem, ID, valueAST);
		}
		if ( elem instanceof TerminalAST ) {
			return checkTokenOptions((TerminalAST)elem, ID, valueAST);
		}
		if ( elem.getType()==ANTLRParser.ACTION ) {
			return false;
		}
		if ( elem.getType()==ANTLRParser.SEMPRED ) {
			Token optionID = ID.token;
			String fileName = optionID.getInputStream().getSourceName();
			if ( valueAST!=null && !Grammar.semPredOptions.contains(optionID.getText()) ) {
				g.tool.errMgr.grammarError(ErrorType.ILLEGAL_OPTION,
										   fileName,
										   optionID,
										   optionID.getText());
				return false;
			}
		}
		return false;
	}
Check option is appropriate for elem; parent of ID is ELEMENT_OPTIONS
tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java