ExpressionVisitor.java revision 4ba16229a40e9758db86d4fb1df5119fdcb8aa2a
1d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/*
2d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Copyright (C) 2015 The Android Open Source Project
3d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *
4d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
5d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * you may not use this file except in compliance with the License.
6d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * You may obtain a copy of the License at
7d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *
8d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
9d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *
10d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Unless required by applicable law or agreed to in writing, software
11d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
12d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * See the License for the specific language governing permissions and
14d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * limitations under the License.
15d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */
16d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
17fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool;
18d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
194ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Guptaimport com.google.common.base.Objects;
204ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta
21c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport org.antlr.v4.runtime.ParserRuleContext;
22d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport org.antlr.v4.runtime.misc.NotNull;
23d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport org.antlr.v4.runtime.tree.ParseTree;
24c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport org.antlr.v4.runtime.tree.ParseTreeListener;
25d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport org.antlr.v4.runtime.tree.TerminalNode;
26fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount
27fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.parser.BindingExpressionBaseVisitor;
28fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.parser.BindingExpressionParser;
29c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.parser.BindingExpressionParser.AndOrOpContext;
30c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.parser.BindingExpressionParser.BinaryOpContext;
31c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.parser.BindingExpressionParser.BitShiftOpContext;
32c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.parser.BindingExpressionParser.InstanceOfOpContext;
33c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.parser.BindingExpressionParser.UnaryOpContext;
34fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Expr;
35fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ExprModel;
36fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.StaticIdentifierExpr;
37fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer;
38fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelClass;
392611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyarimport android.databinding.tool.util.Preconditions;
40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
41d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.ArrayList;
42d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.List;
43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
44d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarpublic class ExpressionVisitor extends BindingExpressionBaseVisitor<Expr> {
45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private final ExprModel mModel;
46c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    private ParseTreeListener mParseTreeListener;
47c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public ExpressionVisitor(ExprModel model) {
49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mModel = model;
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
52c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public void setParseTreeListener(ParseTreeListener parseTreeListener) {
53c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        mParseTreeListener = parseTreeListener;
54c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
55c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
56c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    private void onEnter(ParserRuleContext context) {
57c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (mParseTreeListener != null) {
58c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            mParseTreeListener.enterEveryRule(context);
59c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
60c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
61c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
62c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    private void onExit(ParserRuleContext context) {
63c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        if (mParseTreeListener != null) {
64c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            mParseTreeListener.exitEveryRule(context);
65c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
66c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    }
67c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitStringLiteral(@NotNull BindingExpressionParser.StringLiteralContext ctx) {
70c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
71c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
72c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            final String javaString;
73c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            if (ctx.SingleQuoteString() != null) {
74c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                String str = ctx.SingleQuoteString().getText();
75c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                String contents = str.substring(1, str.length() - 1);
76c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                contents = contents.replace("\"", "\\\"").replace("\\`", "`");
77c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                javaString = '"' + contents + '"';
78c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            } else {
79c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                javaString = ctx.DoubleQuoteString().getText();
80c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            }
81c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.symbol(javaString, String.class);
82c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
83c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
84d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
85d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitGrouping(@NotNull BindingExpressionParser.GroupingContext ctx) {
89c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
90c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
91c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            Preconditions.check(ctx.children.size() == 3, "Grouping expression should have"
92c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    + " 3 children. # of children: %d", ctx.children.size());
93c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.group(ctx.children.get(1).accept(this));
94c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
95c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
96c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
97d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
98d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
99d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
100d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitBindingSyntax(@NotNull BindingExpressionParser.BindingSyntaxContext ctx) {
101d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        try {
102c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
103d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            // TODO handle defaults
104d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return mModel.bindingExpr(ctx.expression().accept(this));
105d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        } catch (Exception e) {
106d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            System.out.println("Error while parsing! " + ctx.getText());
107d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            e.printStackTrace();
108895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            throw new RuntimeException(e);
109c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
110c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
111d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
112d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
113d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
114d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
115d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitDotOp(@NotNull BindingExpressionParser.DotOpContext ctx) {
116c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
117c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
118c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            ModelAnalyzer analyzer = ModelAnalyzer.getInstance();
119c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            ModelClass modelClass = analyzer.findClass(ctx.getText(), mModel.getImports());
120c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            if (modelClass == null) {
121c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                return mModel.field(ctx.expression().accept(this),
122c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                        ctx.Identifier().getSymbol().getText());
123c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            } else {
124c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                String name = modelClass.toJavaCode();
125c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                StaticIdentifierExpr expr = mModel.staticIdentifier(name);
126c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                expr.setUserDefinedType(name);
127c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                return expr;
128c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            }
129c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
130c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
1318e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        }
132d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
133d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
134d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
135d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitQuestionQuestionOp(@NotNull BindingExpressionParser.QuestionQuestionOpContext ctx) {
136c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
137c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
138c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            final Expr left = ctx.left.accept(this);
139c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.ternary(mModel.comparison("==", left, mModel.symbol("null", Object.class)),
140c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    ctx.right.accept(this), left);
141c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
142c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
143c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
144d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
145d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
146d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
147d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitTerminal(@NotNull TerminalNode node) {
148c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
149c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter((ParserRuleContext) node.getParent().getRuleContext());
150c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            final int type = node.getSymbol().getType();
151c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            Class classType;
152c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            switch (type) {
153c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                case BindingExpressionParser.IntegerLiteral:
154c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    classType = int.class;
155c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    break;
156c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                case BindingExpressionParser.FloatingPointLiteral:
157c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    classType = float.class;
158c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    break;
159c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                case BindingExpressionParser.BooleanLiteral:
160c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    classType = boolean.class;
161c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    break;
162c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                case BindingExpressionParser.CharacterLiteral:
163c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    classType = char.class;
164c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    break;
165c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                case BindingExpressionParser.SingleQuoteString:
166c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                case BindingExpressionParser.DoubleQuoteString:
167c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    classType = String.class;
168c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    break;
169c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                case BindingExpressionParser.NullLiteral:
170c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    classType = Object.class;
171c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    break;
172c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                default:
173c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    throw new RuntimeException("cannot create expression from terminal node " +
174c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                            node.toString());
175c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            }
176c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.symbol(node.getText(), classType);
177c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
178c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit((ParserRuleContext) node.getParent().getRuleContext());
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitComparisonOp(@NotNull BindingExpressionParser.ComparisonOpContext ctx) {
184c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
185c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
186c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.comparison(ctx.op.getText(), ctx.left.accept(this), ctx.right.accept(this));
187c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
188c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
189c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
190d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
191d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
192d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
193d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitIdentifier(@NotNull BindingExpressionParser.IdentifierContext ctx) {
194c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
195c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
196c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.identifier(ctx.getText());
197c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
198c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
199c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
200d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
201d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
202d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
203d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitTernaryOp(@NotNull BindingExpressionParser.TernaryOpContext ctx) {
204c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
205c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
206c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.ternary(ctx.left.accept(this), ctx.iftrue.accept(this),
207c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    ctx.iffalse.accept(this));
208c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
209c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
210c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
211c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
212d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
213d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
214d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
215d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitMethodInvocation(
216d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            @NotNull BindingExpressionParser.MethodInvocationContext ctx) {
217c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
218c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
219c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            List<Expr> args = new ArrayList<Expr>();
220c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            if (ctx.args != null) {
221c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                for (ParseTree item : ctx.args.children) {
2224ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta                    if (Objects.equal(item.getText(), ",")) {
223c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                        continue;
224c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    }
225c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    args.add(item.accept(this));
226d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
227d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
228c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.methodCall(ctx.target.accept(this),
229c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    ctx.Identifier().getText(), args);
230c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
231c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
234d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
236d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitMathOp(@NotNull BindingExpressionParser.MathOpContext ctx) {
237c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
238c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
239c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.math(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
240c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
241c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
242c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
243d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
244d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
245c752a5f795baf6df435ef60881316cb748df407cGeorge Mount    @Override
246c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    public Expr visitAndOrOp(@NotNull AndOrOpContext ctx) {
247c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
248c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
249c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.logical(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
250c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
251c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
252c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
253c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    }
254c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount
255c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    @Override
256c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    public Expr visitBinaryOp(@NotNull BinaryOpContext ctx) {
257c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
258c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
259c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.math(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
260c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
261c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
262c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
263c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    }
264c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount
265c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    @Override
266c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    public Expr visitBitShiftOp(@NotNull BitShiftOpContext ctx) {
267c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
268c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
269c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.bitshift(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
270c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
271c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
272c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
273c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    }
274c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount
275c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    @Override
276c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    public Expr visitInstanceOfOp(@NotNull InstanceOfOpContext ctx) {
277c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
278c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
279c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.instanceOfOp(ctx.expression().accept(this), ctx.type().getText());
280c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
281c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
282c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
283c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    }
284c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount
285c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    @Override
286c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    public Expr visitUnaryOp(@NotNull UnaryOpContext ctx) {
287c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
288c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
289c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.unary(ctx.op.getText(), ctx.expression().accept(this));
290c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
291c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
292c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
293c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    }
294c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount
295c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount    @Override
296ae7cb82316e351c488ee3b9c7226602321f34301George Mount    public Expr visitResources(@NotNull BindingExpressionParser.ResourcesContext ctx) {
297c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
298c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
299c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            final List<Expr> args = new ArrayList<Expr>();
300c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            if (ctx.resourceParameters() != null) {
301c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                for (ParseTree item : ctx.resourceParameters().expressionList().children) {
3024ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta                    if (Objects.equal(item.getText(), ",")) {
303c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                        continue;
304c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    }
305c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    args.add(item.accept(this));
306ae7cb82316e351c488ee3b9c7226602321f34301George Mount                }
307ae7cb82316e351c488ee3b9c7226602321f34301George Mount            }
308c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            final String resourceReference = ctx.ResourceReference().getText();
309c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            final int colonIndex = resourceReference.indexOf(':');
310c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            final int slashIndex = resourceReference.indexOf('/');
311c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            final String packageName = colonIndex < 0 ? null :
312c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    resourceReference.substring(1, colonIndex).trim();
313c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            final int startIndex = Math.max(1, colonIndex + 1);
314c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            final String resourceType = resourceReference.substring(startIndex, slashIndex).trim();
315c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            final String resourceName = resourceReference.substring(slashIndex + 1).trim();
316c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.resourceExpr(packageName, resourceType, resourceName, args);
317c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
318c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
319ae7cb82316e351c488ee3b9c7226602321f34301George Mount        }
320c752a5f795baf6df435ef60881316cb748df407cGeorge Mount    }
321c752a5f795baf6df435ef60881316cb748df407cGeorge Mount
3225cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    @Override
3235cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    public Expr visitBracketOp(@NotNull BindingExpressionParser.BracketOpContext ctx) {
324c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
325c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
326c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.bracketExpr(visit(ctx.expression(0)), visit(ctx.expression(1)));
327c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
328c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
329c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
3305cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
3315cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
332e4b93061ac703e48fc2c9994c9059ed016f05559George Mount    @Override
333e4b93061ac703e48fc2c9994c9059ed016f05559George Mount    public Expr visitCastOp(@NotNull BindingExpressionParser.CastOpContext ctx) {
334c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        try {
335c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onEnter(ctx);
336c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mModel.castExpr(ctx.type().getText(), visit(ctx.expression()));
337c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        } finally {
338c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            onExit(ctx);
339c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
340e4b93061ac703e48fc2c9994c9059ed016f05559George Mount    }
341d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
342