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 17 package android.databinding.tool; 18 19 import org.antlr.v4.runtime.ANTLRInputStream; 20 import org.antlr.v4.runtime.BaseErrorListener; 21 import org.antlr.v4.runtime.CommonTokenStream; 22 import org.antlr.v4.runtime.ParserRuleContext; 23 import org.antlr.v4.runtime.RecognitionException; 24 import org.antlr.v4.runtime.Recognizer; 25 import org.antlr.v4.runtime.Token; 26 import org.antlr.v4.runtime.misc.Nullable; 27 import org.antlr.v4.runtime.tree.ErrorNode; 28 import org.antlr.v4.runtime.tree.ParseTreeListener; 29 import org.antlr.v4.runtime.tree.TerminalNode; 30 31 import android.databinding.parser.BindingExpressionLexer; 32 import android.databinding.parser.BindingExpressionParser; 33 import android.databinding.tool.expr.Expr; 34 import android.databinding.tool.expr.ExprModel; 35 import android.databinding.tool.processing.ErrorMessages; 36 import android.databinding.tool.store.Location; 37 import android.databinding.tool.util.L; 38 import android.databinding.tool.util.Preconditions; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 43 public class ExpressionParser { 44 final ExprModel mModel; 45 final ExpressionVisitor visitor; 46 47 public ExpressionParser(ExprModel model) { 48 mModel = model; 49 visitor = new ExpressionVisitor(mModel); 50 } 51 52 public Expr parse(String input, @Nullable Location locationInFile) { 53 ANTLRInputStream inputStream = new ANTLRInputStream(input); 54 BindingExpressionLexer lexer = new BindingExpressionLexer(inputStream); 55 CommonTokenStream tokenStream = new CommonTokenStream(lexer); 56 final BindingExpressionParser parser = new BindingExpressionParser(tokenStream); 57 parser.addErrorListener(new BaseErrorListener() { 58 @Override 59 public <T extends Token> void syntaxError(Recognizer<T, ?> recognizer, 60 @Nullable T offendingSymbol, int line, int charPositionInLine, String msg, 61 @Nullable RecognitionException e) { 62 L.e(ErrorMessages.SYNTAX_ERROR, msg); 63 } 64 }); 65 BindingExpressionParser.BindingSyntaxContext root = parser.bindingSyntax(); 66 try { 67 mModel.setCurrentLocationInFile(locationInFile); 68 visitor.setParseTreeListener(new ParseTreeListener() { 69 List<ParserRuleContext> mStack = new ArrayList<ParserRuleContext>(); 70 @Override 71 public void visitTerminal(TerminalNode node) { 72 } 73 74 @Override 75 public void visitErrorNode(ErrorNode node) { 76 } 77 78 @Override 79 public void enterEveryRule(ParserRuleContext ctx) { 80 mStack.add(ctx); 81 mModel.setCurrentParserContext(ctx); 82 } 83 84 @Override 85 public void exitEveryRule(ParserRuleContext ctx) { 86 Preconditions.check(ctx == mStack.get(mStack.size() - 1), 87 "Inconsistent exit from context. Received %s, expecting %s", 88 ctx.toInfoString(parser), 89 mStack.get(mStack.size() - 1).toInfoString(parser)); 90 mStack.remove(mStack.size() - 1); 91 if (mStack.size() > 0) { 92 mModel.setCurrentParserContext(mStack.get(mStack.size() - 1)); 93 } else { 94 mModel.setCurrentParserContext(null); 95 } 96 } 97 }); 98 return root.accept(visitor); 99 } finally { 100 mModel.setCurrentLocationInFile(null); 101 } 102 } 103 104 public ExprModel getModel() { 105 return mModel; 106 } 107 } 108