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 19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.parser.BindingExpressionBaseVisitor; 20fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.parser.BindingExpressionParser; 21c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.parser.BindingExpressionParser.AndOrOpContext; 22c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.parser.BindingExpressionParser.BinaryOpContext; 23c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.parser.BindingExpressionParser.BitShiftOpContext; 24c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.parser.BindingExpressionParser.InstanceOfOpContext; 25c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.parser.BindingExpressionParser.UnaryOpContext; 266047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.expr.CallbackExprModel; 27fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Expr; 28fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ExprModel; 29fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.StaticIdentifierExpr; 30fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer; 31fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelClass; 322611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyarimport android.databinding.tool.util.Preconditions; 33d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 3415b6682cf3505b117329e2190967c92a89b179e9Yigit Boyarimport com.android.annotations.NonNull; 35b522c7650bf7d9ec566845bc9eb37e761eea853dGeorge Mountimport com.google.common.base.Objects; 36b522c7650bf7d9ec566845bc9eb37e761eea853dGeorge Mount 37b522c7650bf7d9ec566845bc9eb37e761eea853dGeorge Mountimport org.antlr.v4.runtime.ParserRuleContext; 38b522c7650bf7d9ec566845bc9eb37e761eea853dGeorge Mountimport org.antlr.v4.runtime.tree.ParseTree; 39b522c7650bf7d9ec566845bc9eb37e761eea853dGeorge Mountimport org.antlr.v4.runtime.tree.ParseTreeListener; 40b522c7650bf7d9ec566845bc9eb37e761eea853dGeorge Mountimport org.antlr.v4.runtime.tree.TerminalNode; 41b522c7650bf7d9ec566845bc9eb37e761eea853dGeorge Mount 426047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport java.util.ArrayDeque; 43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.ArrayList; 44d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.List; 45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 4615b6682cf3505b117329e2190967c92a89b179e9Yigit Boyarclass ExpressionVisitor extends BindingExpressionBaseVisitor<Expr> { 476047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar private ExprModel mModel; 48c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar private ParseTreeListener mParseTreeListener; 496047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar private ArrayDeque<ExprModel> mModelStack = new ArrayDeque<ExprModel>(); 5078dc9ae6d67ae94bf3f637eeea0848e4f700b7a3George Mount private BindingTarget mTarget; 51c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 5215b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar ExpressionVisitor(ExprModel model) { 53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mModel = model; 54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 5615b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar void setParseTreeListener(ParseTreeListener parseTreeListener) { 57c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar mParseTreeListener = parseTreeListener; 58c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 59c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 6078dc9ae6d67ae94bf3f637eeea0848e4f700b7a3George Mount public void setBindingTarget(BindingTarget bindingTarget) { 6178dc9ae6d67ae94bf3f637eeea0848e4f700b7a3George Mount mTarget = bindingTarget; 6278dc9ae6d67ae94bf3f637eeea0848e4f700b7a3George Mount } 6378dc9ae6d67ae94bf3f637eeea0848e4f700b7a3George Mount 64c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar private void onEnter(ParserRuleContext context) { 65c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar if (mParseTreeListener != null) { 66c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar mParseTreeListener.enterEveryRule(context); 67c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 68c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 69c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 70c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar private void onExit(ParserRuleContext context) { 71c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar if (mParseTreeListener != null) { 72c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar mParseTreeListener.exitEveryRule(context); 73c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 74c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 75c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 766047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar private void pushModel(ExprModel model) { 776047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Preconditions.checkNotNull(mModel, "Cannot put empty model to stack"); 786047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Preconditions.checkNotNull(model, "Cannot set null model"); 796047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar mModelStack.push(mModel); 806047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar mModel = model; 816047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 826047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 836047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar private void popModel() { 846047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Preconditions.checkNotNull(mModel, "Cannot have empty mdoel stack"); 856047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Preconditions.check(mModelStack.size() > 0, "Cannot have empty model stack"); 866047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar mModel = mModelStack.pop(); 876047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 886047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 896047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 9015b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitRootLambda(@NonNull BindingExpressionParser.RootLambdaContext ctx) { 916047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar try { 926047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar onEnter(ctx); 936047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar CallbackExprModel callbackModel = new CallbackExprModel(mModel); 946047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar ExprModel prev = mModel; 956047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar pushModel(callbackModel); 966047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final BindingExpressionParser.LambdaExpressionContext lambdaCtx = ctx 976047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar .lambdaExpression(); 986047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar lambdaCtx.args.accept(this); 996047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return prev.lambdaExpr(lambdaCtx.expression().accept(this), callbackModel); 1006047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } finally { 1016047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar popModel(); 1026047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar onExit(ctx); 1036047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1046047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1056047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1066047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 1076047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public Expr visitSingleLambdaParameter( 10815b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar @NonNull BindingExpressionParser.SingleLambdaParameterContext ctx) { 1096047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar try { 1106047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar onEnter(ctx); 1116047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Preconditions.check(mModel instanceof CallbackExprModel, "Lambdas can only be used in" 1126047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar + " callbacks."); 1136047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // just add it to the callback model as identifier 1146047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar ((CallbackExprModel) mModel).callbackArg(ctx.getText()); 1156047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return null; 1166047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } finally { 1176047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar onExit(ctx); 1186047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1196047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1206047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1216047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 1226047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public Expr visitLambdaParameterList( 12315b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar @NonNull BindingExpressionParser.LambdaParameterListContext ctx) { 1246047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar try { 1256047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar onEnter(ctx); 1266047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Preconditions.check(mModel instanceof CallbackExprModel, "Lambdas can only be used in" 1276047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar + " callbacks."); 1286047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (ctx.params != null) { 1296047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar for (ParseTree item : ctx.params.children) { 1306047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (Objects.equal(item.getText(), ",")) { 1316047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar continue; 1326047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1336047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // just add them to the callback model as identifiers 1346047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar ((CallbackExprModel) mModel).callbackArg(item.getText()); 1356047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1366047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1376047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return null; 1386047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } finally { 1396047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar onExit(ctx); 1406047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1416047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1426047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 143d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 14415b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitStringLiteral(@NonNull BindingExpressionParser.StringLiteralContext ctx) { 145c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 146c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 147c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final String javaString; 148c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar if (ctx.SingleQuoteString() != null) { 149c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar String str = ctx.SingleQuoteString().getText(); 150c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar String contents = str.substring(1, str.length() - 1); 151c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar contents = contents.replace("\"", "\\\"").replace("\\`", "`"); 152c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar javaString = '"' + contents + '"'; 153c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } else { 154c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar javaString = ctx.DoubleQuoteString().getText(); 155c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 156c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.symbol(javaString, String.class); 157c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 158c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 159d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 16315b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitRootExpr(@NonNull BindingExpressionParser.RootExprContext ctx) { 164c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 165c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 1666047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // TODO handle defaults 1676047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mModel.bindingExpr(ctx.expression().accept(this)); 1686047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } catch (Exception e) { 1696047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar System.out.println("Error while parsing! " + ctx.getText()); 1706047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar e.printStackTrace(); 1716047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar throw new RuntimeException(e); 172c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 173c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 174c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 175d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 176d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 17815b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitGrouping(@NonNull BindingExpressionParser.GroupingContext ctx) { 179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar try { 180c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 1816047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Preconditions.check(ctx.children.size() == 3, "Grouping expression should have" 1826047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar + " 3 children. # of children: %d", ctx.children.size()); 183b522c7650bf7d9ec566845bc9eb37e761eea853dGeorge Mount return ctx.children.get(1).accept(this); 184c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 185c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 188d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 189d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 19015b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitDotOp(@NonNull BindingExpressionParser.DotOpContext ctx) { 191c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 192c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 193c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar ModelAnalyzer analyzer = ModelAnalyzer.getInstance(); 194c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar ModelClass modelClass = analyzer.findClass(ctx.getText(), mModel.getImports()); 195c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar if (modelClass == null) { 196c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.field(ctx.expression().accept(this), 197c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar ctx.Identifier().getSymbol().getText()); 198c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } else { 199c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar String name = modelClass.toJavaCode(); 200c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar StaticIdentifierExpr expr = mModel.staticIdentifier(name); 201c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar expr.setUserDefinedType(name); 202c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return expr; 203c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 204c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 205c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 2068e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 207d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 208d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 209d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 21015b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitFunctionRef(@NonNull BindingExpressionParser.FunctionRefContext ctx) { 211c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount try { 212c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount onEnter(ctx); 213c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount return mModel.methodReference(ctx.expression().accept(this), 214c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount ctx.Identifier().getSymbol().getText()); 215c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount } finally { 216c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount onExit(ctx); 217c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount } 218c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount } 219c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount 220c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount @Override 22115b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitQuestionQuestionOp( 22215b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar @NonNull BindingExpressionParser.QuestionQuestionOpContext ctx) { 223c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 224c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 225c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final Expr left = ctx.left.accept(this); 226c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.ternary(mModel.comparison("==", left, mModel.symbol("null", Object.class)), 227c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar ctx.right.accept(this), left); 228c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 229c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 230c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 23415b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitTerminal(@NonNull TerminalNode node) { 235c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 23615b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar onEnter((ParserRuleContext) node.getParent()); 237c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final int type = node.getSymbol().getType(); 238c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar Class classType; 239c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar switch (type) { 240c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar case BindingExpressionParser.IntegerLiteral: 241c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar classType = int.class; 242c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar break; 243c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar case BindingExpressionParser.FloatingPointLiteral: 244c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar classType = float.class; 245c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar break; 246c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar case BindingExpressionParser.BooleanLiteral: 247c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar classType = boolean.class; 248c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar break; 249c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar case BindingExpressionParser.CharacterLiteral: 250c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar classType = char.class; 251c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar break; 252c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar case BindingExpressionParser.SingleQuoteString: 253c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar case BindingExpressionParser.DoubleQuoteString: 254c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar classType = String.class; 255c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar break; 256c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar case BindingExpressionParser.NullLiteral: 257c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar classType = Object.class; 258c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar break; 2596047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar case BindingExpressionParser.VoidLiteral: 2606047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar classType = void.class; 2616047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar break; 262c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar default: 263c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar throw new RuntimeException("cannot create expression from terminal node " + 264c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar node.toString()); 265c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 266c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.symbol(node.getText(), classType); 267c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 26815b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar onExit((ParserRuleContext) node.getParent()); 269d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 270d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 271d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 272d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 27315b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitComparisonOp(@NonNull BindingExpressionParser.ComparisonOpContext ctx) { 274c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 275c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 276c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.comparison(ctx.op.getText(), ctx.left.accept(this), ctx.right.accept(this)); 277c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 278c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 279c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 280d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 281d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 282d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 28315b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitIdentifier(@NonNull BindingExpressionParser.IdentifierContext ctx) { 284c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 285c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 286c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.identifier(ctx.getText()); 287c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 288c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 289c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 290d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 291d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 292d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 29315b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitTernaryOp(@NonNull BindingExpressionParser.TernaryOpContext ctx) { 294c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 295c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 296c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.ternary(ctx.left.accept(this), ctx.iftrue.accept(this), 297c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar ctx.iffalse.accept(this)); 298c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 299c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 300c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 301c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 302d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 303d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 304d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 305d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public Expr visitMethodInvocation( 30615b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar @NonNull BindingExpressionParser.MethodInvocationContext ctx) { 307c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 308c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 309c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar List<Expr> args = new ArrayList<Expr>(); 310c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar if (ctx.args != null) { 311c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar for (ParseTree item : ctx.args.children) { 3124ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta if (Objects.equal(item.getText(), ",")) { 313c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar continue; 314c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 315c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar args.add(item.accept(this)); 316d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 317d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 318c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.methodCall(ctx.target.accept(this), 319c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar ctx.Identifier().getText(), args); 320c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 321c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 322d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 323d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 324d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 325d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 32615b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitMathOp(@NonNull BindingExpressionParser.MathOpContext ctx) { 327c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 328c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 329c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.math(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this)); 330c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 331c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 332c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 333d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 334d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 335c752a5f795baf6df435ef60881316cb748df407cGeorge Mount @Override 33615b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitAndOrOp(@NonNull AndOrOpContext ctx) { 337c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 338c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 339c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.logical(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this)); 340c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 341c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 342c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 343c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount } 344c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount 345c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount @Override 34615b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitBinaryOp(@NonNull BinaryOpContext ctx) { 347c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 348c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 349c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.math(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this)); 350c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 351c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 352c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 353c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount } 354c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount 355c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount @Override 35615b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitBitShiftOp(@NonNull BitShiftOpContext ctx) { 357c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 358c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 359c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.bitshift(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this)); 360c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 361c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 362c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 363c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount } 364c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount 365c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount @Override 36615b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitInstanceOfOp(@NonNull InstanceOfOpContext ctx) { 367c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 368c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 369c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.instanceOfOp(ctx.expression().accept(this), ctx.type().getText()); 370c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 371c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 372c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 373c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount } 374c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount 375c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount @Override 37615b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitUnaryOp(@NonNull UnaryOpContext ctx) { 377c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 378c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 379c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.unary(ctx.op.getText(), ctx.expression().accept(this)); 380c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 381c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 382c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 383c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount } 384c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount 385c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount @Override 38615b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitResources(@NonNull BindingExpressionParser.ResourcesContext ctx) { 387c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 388c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 389c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final List<Expr> args = new ArrayList<Expr>(); 390c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar if (ctx.resourceParameters() != null) { 391c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar for (ParseTree item : ctx.resourceParameters().expressionList().children) { 3924ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta if (Objects.equal(item.getText(), ",")) { 393c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar continue; 394c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 395c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar args.add(item.accept(this)); 396ae7cb82316e351c488ee3b9c7226602321f34301George Mount } 397ae7cb82316e351c488ee3b9c7226602321f34301George Mount } 398c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final String resourceReference = ctx.ResourceReference().getText(); 399c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final int colonIndex = resourceReference.indexOf(':'); 400c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final int slashIndex = resourceReference.indexOf('/'); 401c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final String packageName = colonIndex < 0 ? null : 402c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar resourceReference.substring(1, colonIndex).trim(); 403c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final int startIndex = Math.max(1, colonIndex + 1); 404c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final String resourceType = resourceReference.substring(startIndex, slashIndex).trim(); 405c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final String resourceName = resourceReference.substring(slashIndex + 1).trim(); 40678dc9ae6d67ae94bf3f637eeea0848e4f700b7a3George Mount return mModel.resourceExpr(mTarget, packageName, resourceType, resourceName, args); 407c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 408c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 409ae7cb82316e351c488ee3b9c7226602321f34301George Mount } 410c752a5f795baf6df435ef60881316cb748df407cGeorge Mount } 411c752a5f795baf6df435ef60881316cb748df407cGeorge Mount 4125cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount @Override 41315b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitBracketOp(@NonNull BindingExpressionParser.BracketOpContext ctx) { 414c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 415c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 416c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.bracketExpr(visit(ctx.expression(0)), visit(ctx.expression(1))); 417c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 418c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 419c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 4205cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 4215cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 422e4b93061ac703e48fc2c9994c9059ed016f05559George Mount @Override 42315b6682cf3505b117329e2190967c92a89b179e9Yigit Boyar public Expr visitCastOp(@NonNull BindingExpressionParser.CastOpContext ctx) { 424c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar try { 425c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onEnter(ctx); 426c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mModel.castExpr(ctx.type().getText(), visit(ctx.expression())); 427c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } finally { 428c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar onExit(ctx); 429c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 430e4b93061ac703e48fc2c9994c9059ed016f05559George Mount } 431d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar} 432