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