1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.databinding.tool; 18 19import org.antlr.v4.runtime.ANTLRInputStream; 20import org.antlr.v4.runtime.BaseErrorListener; 21import org.antlr.v4.runtime.CommonTokenStream; 22import org.antlr.v4.runtime.ParserRuleContext; 23import org.antlr.v4.runtime.RecognitionException; 24import org.antlr.v4.runtime.Recognizer; 25import org.antlr.v4.runtime.Token; 26import org.antlr.v4.runtime.tree.ErrorNode; 27import org.antlr.v4.runtime.tree.ParseTreeListener; 28import org.antlr.v4.runtime.tree.TerminalNode; 29 30import android.databinding.parser.BindingExpressionLexer; 31import android.databinding.parser.BindingExpressionParser; 32import android.databinding.tool.expr.Expr; 33import android.databinding.tool.expr.ExprModel; 34import android.databinding.tool.processing.ErrorMessages; 35import android.databinding.tool.store.Location; 36import android.databinding.tool.util.L; 37import android.databinding.tool.util.Preconditions; 38 39import com.android.annotations.Nullable; 40 41import java.util.ArrayList; 42import java.util.List; 43 44public class ExpressionParser { 45 final ExprModel mModel; 46 final ExpressionVisitor visitor; 47 48 public ExpressionParser(ExprModel model) { 49 mModel = model; 50 visitor = new ExpressionVisitor(mModel); 51 } 52 53 public Expr parse(String input, @Nullable Location locationInFile, BindingTarget target) { 54 ANTLRInputStream inputStream = new ANTLRInputStream(input); 55 BindingExpressionLexer lexer = new BindingExpressionLexer(inputStream); 56 CommonTokenStream tokenStream = new CommonTokenStream(lexer); 57 final BindingExpressionParser parser = new BindingExpressionParser(tokenStream); 58 visitor.setBindingTarget(target); 59 parser.addErrorListener(new BaseErrorListener() { 60 @Override 61 public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, 62 int charPositionInLine, String msg, RecognitionException e) { 63 L.e(ErrorMessages.SYNTAX_ERROR, msg); 64 } 65 }); 66 BindingExpressionParser.BindingSyntaxContext root = parser.bindingSyntax(); 67 try { 68 mModel.setCurrentLocationInFile(locationInFile); 69 visitor.setParseTreeListener(new ParseTreeListener() { 70 List<ParserRuleContext> mStack = new ArrayList<ParserRuleContext>(); 71 @Override 72 public void visitTerminal(TerminalNode node) { 73 } 74 75 @Override 76 public void visitErrorNode(ErrorNode node) { 77 } 78 79 @Override 80 public void enterEveryRule(ParserRuleContext ctx) { 81 mStack.add(ctx); 82 mModel.setCurrentParserContext(ctx); 83 } 84 85 @Override 86 public void exitEveryRule(ParserRuleContext ctx) { 87 Preconditions.check(ctx == mStack.get(mStack.size() - 1), 88 "Inconsistent exit from context. Received %s, expecting %s", 89 ctx.toInfoString(parser), 90 mStack.get(mStack.size() - 1).toInfoString(parser)); 91 mStack.remove(mStack.size() - 1); 92 if (mStack.size() > 0) { 93 mModel.setCurrentParserContext(mStack.get(mStack.size() - 1)); 94 } else { 95 mModel.setCurrentParserContext(null); 96 } 97 } 98 }); 99 return root.accept(visitor); 100 } finally { 101 mModel.setCurrentLocationInFile(null); 102 } 103 } 104 105 public ExprModel getModel() { 106 return mModel; 107 } 108} 109