ExpressionVisitor.java revision 5cd681c345db8f606d7d5a8662e20e059f21a86c
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
1743596c2b2997e40b709627419732100d78a62ff0Yigit Boyarpackage com.android.databinding;
18d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
19d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport com.google.common.base.Preconditions;
20d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2143596c2b2997e40b709627419732100d78a62ff0Yigit Boyarimport com.android.databinding.expr.Expr;
2243596c2b2997e40b709627419732100d78a62ff0Yigit Boyarimport com.android.databinding.expr.ExprModel;
23d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
24d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport org.antlr.v4.runtime.misc.NotNull;
25d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport org.antlr.v4.runtime.tree.ParseTree;
26d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport org.antlr.v4.runtime.tree.TerminalNode;
27d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
28d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.ArrayList;
29d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.List;
30d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.Objects;
31d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
32d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarpublic class ExpressionVisitor extends BindingExpressionBaseVisitor<Expr> {
33d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private final ExprModel mModel;
34d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public ExpressionVisitor(ExprModel model) {
35d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mModel = model;
36d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
37d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
38d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitStringLiteral(@NotNull BindingExpressionParser.StringLiteralContext ctx) {
40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        final String javaString;
41d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (ctx.SingleQuoteString() != null) {
42d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            String str = ctx.SingleQuoteString().getText();
43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            String contents = str.substring(1, str.length() - 1);
44d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            contents = contents.replace("\"", "\\\"").replace("\\`", "`");
45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            javaString = '"' + contents + '"';
46d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        } else {
47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            javaString = ctx.DoubleQuoteString().getText();
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mModel.symbol(javaString, String.class);
51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
52d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitGrouping(@NotNull BindingExpressionParser.GroupingContext ctx) {
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        Preconditions.checkArgument(ctx.children.size() == 1, "Grouping expression should have"
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                + " only 1 child");
57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mModel.group(ctx.children.get(0).accept(this));
58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
61d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitBindingSyntax(@NotNull BindingExpressionParser.BindingSyntaxContext ctx) {
62d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        try {
63d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            // TODO handle defaults
64d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return mModel.bindingExpr(ctx.expression().accept(this));
65d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        } catch (Exception e) {
66d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            System.out.println("Error while parsing! " + ctx.getText());
67d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            e.printStackTrace();
68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            throw e;
69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
73d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitDotOp(@NotNull BindingExpressionParser.DotOpContext ctx) {
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mModel.field(ctx.expression().accept(this),
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                ctx.Identifier().getSymbol().getText());
76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
77d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
78d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
79d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitQuestionQuestionOp(@NotNull BindingExpressionParser.QuestionQuestionOpContext ctx) {
80d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        final Expr left = ctx.left.accept(this);
81d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mModel.ternary(
82d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                mModel.comparison("==", left, mModel.symbol("null", Object.class)),
83d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                left, ctx.right.accept(this));
84d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
85d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitTerminal(@NotNull TerminalNode node) {
88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        final int type = node.getSymbol().getType();
89d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        switch (type) {
90d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            case BindingExpressionParser.IntegerLiteral:
91d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                return mModel.symbol(node.getText(), Integer.class);
92d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            case BindingExpressionParser.FloatingPointLiteral:
93d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                return mModel.symbol(node.getText(), Float.class);
94d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            case BindingExpressionParser.BooleanLiteral:
95d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                return mModel.symbol(node.getText(), Boolean.class);
96d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            case BindingExpressionParser.CharacterLiteral:
97d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                return mModel.symbol(node.getText(), Character.class);
98d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            case BindingExpressionParser.SingleQuoteString:
99d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                return mModel.symbol(node.getText(), String.class);
100d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            case BindingExpressionParser.DoubleQuoteString:
101d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                return mModel.symbol(node.getText(), String.class);
102d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            case BindingExpressionParser.NullLiteral:
103d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                return mModel.symbol(node.getText(), Object.class);
104d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            default:
105d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                throw new RuntimeException("cannot create expression from terminal node " + node.toString());
106d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
107d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
108d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
109d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitComparisonOp(@NotNull BindingExpressionParser.ComparisonOpContext ctx) {
111d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mModel.comparison(ctx.op.getText(), ctx.left.accept(this), ctx.right.accept(this));
112d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
113d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
114d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
115d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitIdentifier(@NotNull BindingExpressionParser.IdentifierContext ctx) {
116d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mModel.identifier(ctx.getText());
117d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
119d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
120d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitTernaryOp(@NotNull BindingExpressionParser.TernaryOpContext ctx) {
121d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mModel.ternary(ctx.left.accept(this), ctx.iftrue.accept(this),
122d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                ctx.iffalse.accept(this));
123d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
124d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
125d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
126d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitMethodInvocation(
127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            @NotNull BindingExpressionParser.MethodInvocationContext ctx) {
128d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        List<Expr> args = new ArrayList<>();
129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (ctx.args != null) {
130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (ParseTree item : ctx.args.children) {
131d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                if (Objects.equals(item.getText(), ",")) {
132d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    continue;
133d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
134d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                args.add(item.accept(this));
135d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
136d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
137d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mModel.methodCall(ctx.target.accept(this),
138d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                ctx.Identifier().getText(), args);
139d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
140d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
142d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr visitMathOp(@NotNull BindingExpressionParser.MathOpContext ctx) {
143d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return mModel.math(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
144d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
145d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
146c752a5f795baf6df435ef60881316cb748df407cGeorge Mount    @Override
147c752a5f795baf6df435ef60881316cb748df407cGeorge Mount    public Expr visitResource(@NotNull BindingExpressionParser.ResourceContext ctx) {
148c752a5f795baf6df435ef60881316cb748df407cGeorge Mount        return mModel.resourceExpr(ctx.getText());
149c752a5f795baf6df435ef60881316cb748df407cGeorge Mount    }
150c752a5f795baf6df435ef60881316cb748df407cGeorge Mount
1515cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    @Override
1525cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    public Expr visitBracketOp(@NotNull BindingExpressionParser.BracketOpContext ctx) {
1535cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        return mModel.bracketExpr(visit(ctx.expression(0)), visit(ctx.expression(1)));
1545cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
1555cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
156d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    //    @Override
157d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    public Expr visitIdentifier(@NotNull BindingExpressionParser.IdentifierContext ctx) {
158d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        final String identifier = ctx.Identifier().getText();
159d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        final VariableRef variableRef = mModel.getOrCreateVariable(identifier, null);
160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        mAccessedVariables.add(variableRef);
161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        return new FieldExpr(variableRef, new ArrayList<VariableRef>(0));
163d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
164d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    @Override
166d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    public Expr visit(@NotNull ParseTree tree) {
167d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        if (tree == null) {
168d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            return null;
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        }
170d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        return super.visit(tree);
171d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
172d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    @Override
174d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    public Expr visitTernaryOp(@NotNull BindingExpressionParser.TernaryOpContext ctx) {
175d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        return new TernaryExpr(ctx.left.accept(this), ctx.iftrue.accept(this), ctx.iffalse.accept(this));
176d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    @Override
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    public Expr visitTerminal(@NotNull TerminalNode node) {
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        final int type = node.getSymbol().getType();
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        switch (type) {
183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            case IntegerLiteral:
184d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                return new SymbolExpr(node.getText(), Integer.class);
185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            case FloatingPointLiteral:
186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                return new SymbolExpr(node.getText(), Float.class);
187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            case BooleanLiteral:
188d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                return new SymbolExpr(node.getText(), Boolean.class);
189d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            case CharacterLiteral:
190d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                return new SymbolExpr(node.getText(), Character.class);
191d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            case SingleQuoteString:
192d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                return new SymbolExpr(node.getText(), String.class);
193d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            case DoubleQuoteString:
194d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                return new SymbolExpr(node.getText(), String.class);
195d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            case NullLiteral:
196d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                return new SymbolExpr(node.getText(), Object.class);
197d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            default:
198d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                throw new RuntimeException("cannot create expression from terminal node " + node.toString());
199d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        }
200d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
201d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
202d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    @Override
203d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    public Expr visitMathOp(@NotNull BindingExpressionParser.MathOpContext ctx) {
204d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        // TODO must support upper cast
205d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        return new OpExpr(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
206d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
207d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
208d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    @Override
209d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    public Expr visitBitShiftOp(@NotNull BindingExpressionParser.BitShiftOpContext ctx) {
210d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        return new BinaryOpExpr(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
211d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
212d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
213d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    @Override
214d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    public Expr visitComparisonOp(@NotNull BindingExpressionParser.ComparisonOpContext ctx) {
215d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        return new ComparisonOpExpr(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
216d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
217d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
218d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    @Override
219d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    public Expr visitBinaryOp(@NotNull BindingExpressionParser.BinaryOpContext ctx) {
220d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        return new BinaryOpExpr(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
221d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
222d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
223d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    @Override
224d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    public Expr visitAndOrOp(@NotNull BindingExpressionParser.AndOrOpContext ctx) {
225d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        return new AndOrOpExpr(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
226d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
227d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
228d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    @Override
229d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    protected Expr aggregateResult(final Expr aggregate, final Expr nextResult) {
230d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        if (aggregate == null) {
231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            return nextResult;
232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        } else {
233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            return new Expr() {
234d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                @org.jetbrains.annotations.NotNull
235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                @Override
236d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                public Class<? extends Object> resolveValueType(
237d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                        @org.jetbrains.annotations.NotNull ClassAnalyzer classAnalyzer) {
238d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                    return classAnalyzer.commonParentOf(aggregate.getResolvedClass(), nextResult.getResolvedClass());
239d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                }
240d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
241d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                @org.jetbrains.annotations.NotNull
242d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                @Override
243d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                public String toReadableString() {
244d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                    return aggregate.toReadableString() + ' ' + nextResult.toReadableString();
245d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                }
246d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
247d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                @org.jetbrains.annotations.NotNull
248d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                @Override
249d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                public String toJava() {
250d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                    return aggregate.toJava() + ' ' + nextResult.toJava();
251d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                }
252d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            };
253d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        }
254d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
255d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
256d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    @Override
257d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    public Expr visitDefaults(@NotNull BindingExpressionParser.DefaultsContext ctx) {
258d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        return visit(ctx.constantValue());
259d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
260d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//
261d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    @Override
262d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    public Expr visitMethodInvocation(
263d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            @NotNull BindingExpressionParser.MethodInvocationContext ctx) {
264d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        final Expr expression = visit(ctx.expression());
265d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        final String methodName = ctx.Identifier().getText();
266d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        final ArrayList<Expr> parameters = new ArrayList<>();
267d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        if (ctx.expressionList() != null) {
268d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            for (BindingExpressionParser.ExpressionContext parameter : ctx.expressionList()
269d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                    .expression()) {
270d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//                parameters.add(visit(parameter));
271d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//            }
272d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        }
273d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//        return new MethodCallExpr(expression, methodName, parameters);
274d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar//    }
275d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
276