• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ExpressionParser(ExprModel model)47     public ExpressionParser(ExprModel model) {
48         mModel = model;
49         visitor = new ExpressionVisitor(mModel);
50     }
51 
parse(String input, @Nullable Location locationInFile)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 
getModel()104     public ExprModel getModel() {
105         return mModel;
106     }
107 }
108