@Override
    public Variable visitAttribute_reference(@NotNull SiddhiQLParser.Attribute_referenceContext ctx) {

//        attribute_reference
//        : hash1='#'? name1=name ('['attribute_index1=attribute_index']')? (hash2='#' name2=name
// ('['attribute_index2=attribute_index']')?)? '.'  attribute_name
//        | attribute_name
//        ;

        Variable variable = Expression.variable((String) visit(ctx.attribute_name()));

        if (ctx.name1 != null && ctx.name2 != null) { //Stream and Function
            variable.setStreamId(ctx.hash1 != null, ctx.not != null,
                    (String) visit(ctx.name1));
            if (ctx.attribute_index1 != null) {
                variable.setStreamIndex((Integer) visit(ctx.attribute_index1));
            }

            variable.setFunctionId((String) visit(ctx.name2));
            if (ctx.attribute_index2 != null) {
                variable.setFunctionIndex((Integer) visit(ctx.attribute_index2));
            }
        } else if (ctx.name1 != null) {   //name2 == null
            if (ctx.hash1 == null) {   //Stream
                variable.setStreamId(false, ctx.not != null, (String) visit(ctx.name1));
                if (ctx.attribute_index1 != null) {
                    variable.setStreamIndex((Integer) visit(ctx.attribute_index1));
                }
            } else {  //InnerStream or Function
                String name = (String) visit(ctx.name1);

                if (ctx.not != null) {
                    throw newSiddhiParserException(ctx, "Found '" + ctx.getText() + "', but only inner or fault " +
                            "can be supported at one!");
                }
                if (activeStreams.contains(SiddhiConstants.INNER_STREAM_FLAG + name)) { //InnerStream
                    variable.setStreamId(true, name);
                    if (ctx.attribute_index1 != null) {
                        variable.setStreamIndex((Integer) visit(ctx.attribute_index1));
                    }

                } else { //Function
                    variable.setFunctionId(name);
                    if (ctx.attribute_index1 != null) {
                        variable.setFunctionIndex((Integer) visit(ctx.attribute_index1));
                    }
                }
            }
        }
        populateQueryContext(variable, ctx);
        return variable;
    }
{@inheritDoc}
<p>The default implementation returns the result of calling
{@link #visitChildren} on {@code ctx}.</p>

@param ctx
modules/siddhi-query-compiler/src/main/java/io/siddhi/query/compiler/internal/SiddhiQLBaseVisitorImpl.java