Upload plugin for new lang
diff --git a/tools/data-binding/compiler/build.gradle b/tools/data-binding/compiler/build.gradle
index bc6046e..07898ed 100644
--- a/tools/data-binding/compiler/build.gradle
+++ b/tools/data-binding/compiler/build.gradle
@@ -33,6 +33,7 @@
 dependencies {
     compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
     compile project(":grammerBuilder")
+    compile project(":xmlGrammer")
 }
 uploadArchives {
     repositories {
diff --git a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/ext/node_ext.kt b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/ext/node_ext.kt
index 97f29a3..4ddc079 100644
--- a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/ext/node_ext.kt
+++ b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/ext/node_ext.kt
@@ -17,6 +17,8 @@
 package com.android.databinding.ext
 
 import org.w3c.dom.Node
+import org.w3c.dom.NodeList
+import java.util.ArrayList
 
 public fun Node.getAndroidId() : String? =
     getAttributes()?.getNamedItem("android:id")?.getNodeValue()
@@ -35,3 +37,20 @@
     return ids
 }
 
+public fun NodeList.forEach( f : (Node) -> Unit ) {
+    val cnt = getLength()
+    if (cnt == 0) return
+    for (i in 0..cnt - 1) {
+        f(item(i))
+    }
+}
+public fun NodeList.toArrayList() : ArrayList<Node> {
+    val cnt = getLength()
+    val arrayList = arrayListOf<Node>()
+    for (i in 0..cnt - 1) {
+        arrayList.add(item(i))
+    }
+    return arrayList
+}
+
+
diff --git a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/main.kt b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/main.kt
index 70d69d6..686bca3 100644
--- a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/main.kt
+++ b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/main.kt
@@ -48,7 +48,15 @@
 import com.android.databinding.vo.VariableScope
 import com.android.databinding.vo.VariableDefinition
 import com.android.databinding.vo.BindingTarget
-
+import javax.xml.namespace.NamespaceContext
+import com.android.databinding.ext.forEach
+import javax.xml.transform.TransformerFactory
+import javax.xml.transform.stream.StreamResult
+import javax.xml.transform.dom.DOMSource
+import java.io.FileOutputStream
+import com.android.databinding.ext.toArrayList
+import com.android.databinding.util.XmlEditor
+import com.android.databinding.util.Log
 
 
 public class KLayoutParser(val appPkg : String, val resourceFolders : kotlin.Iterable<File>,
@@ -57,6 +65,7 @@
     var dbr : DataBinderRenderer by Delegates.notNull()
     var styler : AttrRenderer by Delegates.notNull()
     val viewExprBinderRenderers = arrayListOf<ViewExprBinderRenderer>()
+    var processed = false
     public var classAnalyzer : ClassAnalyzer by Delegates.notNull()
 
     val outputResDir by Delegates.lazy { File(outputResBaseDir, "values") }
@@ -69,6 +78,15 @@
         File(outputBaseDir.getAbsolutePath() + "/" + dbr.pkg.replace('.','/'))
     }
 
+    class object {
+        val XPATH_VARIABLE_DEFINITIONS = "//variable"
+        val XPATH_IMPORT_DEFINITIONS = "//import"
+        //val XPATH_BINDING_EXPR = "//@*[starts-with(name(), 'bind')]"
+        val XPATH_STATIC_BINDING_EXPR = "//@*[starts-with(name(), 'bind')]"
+        val XPATH_BINDING_2_EXPR = "//@*[starts-with(., '{') and substring(., string-length(.)) = '}']"
+        val XPATH_BINDING_ELEMENTS = "$XPATH_BINDING_2_EXPR/.."
+    }
+
     public fun analyzeClasses() {
         viewExprBinderRenderers.forEach {
             it.lb.analyzeVariables()
@@ -77,7 +95,14 @@
 
     fun log (s : String) = System.out.println("LOG:$s");
 
-    public fun process() {
+    public fun processIfNecessary() {
+        if (!processed) {
+            processed = true
+            process()
+        }
+    }
+
+    fun process() {
         val xmlFiles = ArrayList<File>()
         resourceFolders.filter({it.exists()}).forEach {
             findLayoutFolders(it).forEach {
@@ -87,7 +112,7 @@
         //viewBinderRenderers.clear()
         for (xml in xmlFiles) {
             log("xmlFile $xml")
-            val exprBinding = parseXml3(xml)
+            val exprBinding = parseAndStripXml(xml)
             if (exprBinding == null) {
                 log("no bindings in $xml, skipping")
                 continue
@@ -103,7 +128,7 @@
 
     public fun writeAttrFile() {
         outputResDir.mkdirs()
-        writeToFile(File(outputResDir, "bindingattrs.xml"), styler.render())
+//        writeToFile(File(outputResDir, "bindingattrs.xml"), styler.render())
     }
 
     public fun writeDbrFile() : Unit = writeDbrFile(dbrOutputDir)
@@ -149,73 +174,133 @@
     private fun toLayoutId(name:String) : String =
             name.substring(0, name.indexOf("."))
 
-    private fun parseXml3(xml: File) : LayoutExprBinding? {
+    private fun stripBindingTags(xml  : File) {
+        val res = XmlEditor.strip(xml)
+        if (res != null) {
+            Log.d{"file ${xml.getName()} has changed, overwriting ${xml.getAbsolutePath()}"}
+            xml.writeText(res)
+        }
+    }
+
+    private fun stripFileAndGetOriginal(xml : File) : File? {
+        System.out.println("parsing resourceY file ${xml.getAbsolutePath()}")
         val factory = DocumentBuilderFactory.newInstance()
         val builder = factory.newDocumentBuilder()
         val doc = builder.parse(xml)
         val xPathFactory = XPathFactory.newInstance()
         val xPath = xPathFactory.newXPath()
+        val commentElementExpr = xPath.compile("//comment()[starts-with(., \" From: file:\")][last()]")
+        var commentElementNodes = commentElementExpr.evaluate(doc, XPathConstants.NODESET) as NodeList
+        System.out.println("comment element nodes count ${commentElementNodes.getLength()}")
+        if (commentElementNodes.getLength() == 0) {
+            System.out.println("cannot find comment element to find the actual file")
+            return null
+        }
+        val first = commentElementNodes.item(0)
+        val actualFilePath = first.getNodeValue().substring(" From: file:".length()).trim()
+        System.out.println("actual file to parse: ${actualFilePath}")
+        val actualFile = File(actualFilePath)
+        if (!actualFile.canRead()) {
+            System.out.println("cannot find original, skipping. ${actualFile.getAbsolutePath()}")
+            return null
+        }
+
+        // now if file has any binding expressions, find and delete them
+        val variableNodes = getVariableNodes(doc, xPath)
+        var changed = variableNodes.getLength() > 0 //TODO do we need to check more?
+        if (changed) {
+            stripBindingTags(xml)
+        }
+
+        return actualFile
+    }
+
+    private fun parseAndStripXml(xml : File) : LayoutExprBinding? {
+        val original = stripFileAndGetOriginal(xml)
+        return if (original == null) {
+            null
+        } else {
+            parseXml3(original)
+        }
+    }
+
+    private fun parseXml3(xml: File) : LayoutExprBinding? {
+        System.out.println("parsing file ${xml.getAbsolutePath()}")
+        val factory = DocumentBuilderFactory.newInstance()
+        val builder = factory.newDocumentBuilder()
+        val doc = builder.parse(xml)
+
+        val xPathFactory = XPathFactory.newInstance()
+        val xPath = xPathFactory.newXPath()
         //
         val layoutBinding = LayoutExprBinding(doc)
         val exprParser = ExpressionParser()
-        val varsExprs = xPath.compile("//@*[starts-with(name(), 'bind_var')]/..")
-        val varNodes = varsExprs.evaluate(doc, XPathConstants.NODESET) as NodeList
 
-        System.out.println("var node count" + varNodes.getLength())
-        for (i in 0..varNodes.getLength() - 1) {
-            val item = varNodes.item(i)
-            System.out.println("checking variable node $item")
+        val varElementNodes = getVariableNodes(doc, xPath)
+
+        System.out.println("varX element node count" + varElementNodes.getLength())
+        val variableScope = VariableScope(doc)//all variables global for now
+        for (i in 0..varElementNodes.getLength() - 1) {
+            val item = varElementNodes.item(i)
+            System.out.println("checking variable element node $item")
             val attributes = item.getAttributes()
-            val variableScope = VariableScope(item)
-            val attrCount = attributes.getLength()
-            for (j in 0..(attrCount - 1)) {
-                val attr = attributes.item(j)
-                val name = attr.getNodeName()
-                if (name.startsWith("bind_var:")) {
-                    variableScope.variables.add(VariableDefinition(name.substring("bind_var:".length), attr.getNodeValue()))
-                }
-            }
-            layoutBinding.addVariableScope(variableScope)
+            val variableName = attributes.getNamedItem("name").getNodeValue()
+            val variableType = attributes.getNamedItem("type").getNodeValue()
+            System.out.println("name:$variableName type:$variableType")
+            variableScope.variables.add(VariableDefinition(variableName, variableType))
         }
+        layoutBinding.addVariableScope(variableScope)
 
-        val expr = xPath.compile("//@*[starts-with(name(), 'bind')]/..")
-        val nodes = expr.evaluate(doc, XPathConstants.NODESET) as NodeList
-        System.out.println("binding node count " + nodes.getLength())
-        for (i in 0..nodes.getLength() - 1) {
-            val item = nodes.item(i)
-            System.out.println("checking node $item")
-            val attributes = item.getAttributes()
+        val bindingNodes = getBindingNodes(doc, xPath)
+        System.out.println("binding node count " + bindingNodes.getLength())
+        bindingNodes.forEach { parent ->
+            System.out.println("binding node: $parent")
+            val attributes = parent.getAttributes()
             val id = attributes.getNamedItem("android:id")
-            if (id == null) {
-                continue
-            }
-            val bindingTarget = BindingTarget(item, id.getNodeValue(), getFullViewClassName(item.getNodeName()))
-            val attrCount = attributes.getLength()
-            for (j in 0..(attrCount - 1)) {
-                val attr = attributes.item(j)
-                val name = attr.getNodeName()
-                if (name.startsWith("bind:")) {
-                    bindingTarget.addBinding(name.substring("bind:".length), exprParser.parse(attr.getNodeValue()))
+            if (id != null) {
+                val bindingTarget = BindingTarget(parent, id.getNodeValue(), getFullViewClassName(parent.getNodeName()))
+                val attrCount = attributes.getLength()
+                for (j in 0..(attrCount - 1)) {
+                    val attr = attributes.item(j)
+                    val value = attr.getNodeValue()
+                    if (value.first() == '{' && value.last() == '}') {
+                        val name = attr.getNodeName().split(":").last()
+                        val strippedValue = value.substring(1, value.length() - 1)
+                        bindingTarget.addBinding(name, exprParser.parse(strippedValue))
+                    }
                 }
+                layoutBinding.bindingTargets.add(bindingTarget)
             }
-            layoutBinding.bindingTargets.add(bindingTarget)
         }
+//        System.out.println("binding node count " + nodes.getLength())
+//        for (i in 0..nodes.getLength() - 1) {
+//            val item = nodes.item(i)
+//            System.out.println("checking node $item")
+//            val attributes = item.getAttributes()
+//            val id = attributes.getNamedItem("android:id")
+//            if (id == null) {
+//                continue
+//            }
+//            val bindingTarget = BindingTarget(item, id.getNodeValue(), getFullViewClassName(item.getNodeName()))
+//            val attrCount = attributes.getLength()
+//            for (j in 0..(attrCount - 1)) {
+//                val attr = attributes.item(j)
+//                val name = attr.getNodeName()
+//                if (name.startsWith("bind:")) {
+//                    bindingTarget.addBinding(name.substring("bind:".length), exprParser.parse(attr.getNodeValue()))
+//                }
+//            }
+//            layoutBinding.bindingTargets.add(bindingTarget)
+//        }
 
-        val convExpr = xPath.compile("//@*[starts-with(name(), 'bind_static')]/..")
-        val convNodes = convExpr.evaluate(doc, XPathConstants.NODESET) as NodeList
-        System.out.println("converter node count " + nodes.getLength())
-        for (i in 0..convNodes.getLength() - 1) {
-            val item = convNodes.item(i)
-            System.out.println("checking conv node $item")
+        val imports = getImportNodes(doc, xPath)
+        System.out.println("import node count " + imports.getLength())
+        imports.forEach { item ->
             val attributes = item.getAttributes()
-            val attrCount = attributes.getLength()
-            for (j in 0..(attrCount - 1)) {
-                val attr = attributes.item(j)
-                val name = attr.getNodeName()
-                if (name.startsWith("bind_static:")) {
-                    layoutBinding.addStaticClass(name.substring("bind_static:".length), attr.getNodeValue())
-                }
-            }
+            val type = attributes.getNamedItem("type").getNodeValue()
+            System.out.println("type ${type}")
+            val alias = attributes.getNamedItem("alias")?.getNodeValue() ?: type.split("\\.").last();
+            layoutBinding.addStaticClass(alias, type)
         }
         if (exprParser.model.variables.size == 0) {
             return null
@@ -225,6 +310,21 @@
         return layoutBinding
     }
 
+    private fun getBindingNodes(doc: Document, xPath: XPath): NodeList {
+        val expr = xPath.compile(XPATH_BINDING_ELEMENTS)
+        return expr.evaluate(doc, XPathConstants.NODESET) as NodeList
+    }
+
+    private fun getVariableNodes(doc: Document?, xPath: XPath): NodeList {
+        val expr = xPath.compile(XPATH_VARIABLE_DEFINITIONS)
+        return expr.evaluate(doc, XPathConstants.NODESET) as NodeList
+    }
+
+    private fun getImportNodes(doc: Document?, xPath: XPath): NodeList {
+        val expr = xPath.compile(XPATH_IMPORT_DEFINITIONS)
+        return expr.evaluate(doc, XPathConstants.NODESET) as NodeList
+    }
+
     private fun findLayoutFolders(resources: File): Array<File> {
         val filenameFilter = object : FilenameFilter {
             override fun accept(dir: File, name: String): Boolean {
diff --git a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/util/Log.kt b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/util/Log.kt
index e8fe446..28c1807 100644
--- a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/util/Log.kt
+++ b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/util/Log.kt
@@ -20,4 +20,8 @@
     fun d(s : String) {
         System.out.println("[debug] $s")
     }
+
+    fun d(f : () -> String) {
+        System.out.println("[debug] ${f()}")
+    }
 }
\ No newline at end of file
diff --git a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/util/XmlEditor.kt b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/util/XmlEditor.kt
new file mode 100644
index 0000000..815108d
--- /dev/null
+++ b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/util/XmlEditor.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.databinding.util
+
+import java.io.File
+import org.antlr.v4.runtime.ANTLRInputStream
+import java.io.FileReader
+import com.android.databinding.XMLLexer
+import org.antlr.v4.runtime.CommonTokenStream
+import com.android.databinding.XMLParser
+import com.android.databinding.log
+import com.android.databinding.XMLParserBaseVisitor
+import com.android.databinding.Position
+import com.android.databinding.toPosition
+import com.android.databinding.toEndPosition
+import java.util.Comparator
+
+/**
+ * Ugly inefficient class to strip unwanted tags from XML.
+ * Band-aid solution to unblock development
+ */
+object XmlEditor {
+    val reservedElementNames = arrayListOf("variable", "import")
+    val visitor = object : XMLParserBaseVisitor<MutableList<Pair<Position, Position>>>() {
+        override fun visitAttribute(ctx: XMLParser.AttributeContext): MutableList<Pair<Position, Position>>? {
+            log{"attr:${ctx.attrName.getText()} ${ctx.attrValue.getText()}"}
+            if (ctx.attrName.getText().startsWith("bind:")) {
+
+                return arrayListOf(Pair(ctx.getStart().toPosition(), ctx.getStop().toEndPosition()))
+            } else if (ctx.attrValue.getText().startsWith("\"{") && ctx.attrValue.getText().endsWith("}\"")) {
+                return arrayListOf(Pair(ctx.getStart().toPosition(), ctx.getStop().toEndPosition()))
+            }
+
+            //log{"visiting attr: ${ctx.getText()} at location ${ctx.getStart().toS()} ${ctx.getStop().toS()}"}
+            return super<XMLParserBaseVisitor>.visitAttribute(ctx)
+        }
+
+        override fun visitElement(ctx: XMLParser.ElementContext): MutableList<Pair<Position, Position>>? {
+            log{"elm ${ctx.elmName.getText()} || ${ctx.Name()}"}
+            if (reservedElementNames.contains(ctx.elmName?.getText()) || ctx.elmName.getText().startsWith("bind:")) {
+                return arrayListOf(Pair(ctx.getStart().toPosition(), ctx.getStop().toEndPosition()))
+            }
+            return super< XMLParserBaseVisitor>.visitElement(ctx)
+        }
+
+        override fun defaultResult(): MutableList<Pair<Position, Position>>? = arrayListOf()
+
+        override fun aggregateResult(aggregate: MutableList<Pair<Position, Position>>?, nextResult: MutableList<Pair<Position, Position>>?): MutableList<Pair<Position, Position>>? =
+            if (aggregate == null) {
+                nextResult
+            } else if (nextResult == null) {
+                aggregate
+            } else {
+                aggregate.addAll(nextResult)
+                aggregate
+            }
+    }
+
+    fun strip(f : File) : String? {
+        val inputStream = ANTLRInputStream(FileReader(f))
+        val lexer = XMLLexer(inputStream)
+        val tokenStream = CommonTokenStream(lexer)
+        val parser = XMLParser(tokenStream)
+        val expr = parser.document()
+        val parsedExpr = expr.accept(visitor)
+        if (parsedExpr.size() == 0) {
+            return null//nothing to strip
+        }
+        val out = StringBuilder()
+        val lines = f.readLines("utf-8")
+        lines.forEach { out.appendln(it) }
+
+        // TODO we probably don't need to sort
+        val sorted = parsedExpr.sortBy(object : Comparator<Pair<Position, Position>> {
+            override fun compare(o1: Pair<Position, Position>, o2: Pair<Position, Position>): Int {
+                val lineCmp = o1.first.line.compareTo(o2.first.charIndex)
+                if (lineCmp != 0) {
+                    return lineCmp
+                }
+                return o1.first.line.compareTo(o2.first.charIndex)
+            }
+        })
+        var lineStarts = arrayListOf(0)
+        lines.withIndices().forEach {
+            if (it.first > 0) {
+                lineStarts.add(lineStarts[it.first - 1] + lines[it.first - 1].length() + 1)
+            }
+        }
+
+        val seperator = System.lineSeparator().charAt(0)
+        sorted.forEach {
+            val posStart = lineStarts[it.first.line] + it.first.charIndex
+            val posEnd = lineStarts[it.second.line] + it.second.charIndex
+            for( i in posStart..(posEnd - 1)) {
+                if (out.charAt(i) != seperator) {
+                    out.setCharAt(i, ' ')
+                }
+            }
+        }
+
+        return out.toString()
+    }
+}
\ No newline at end of file
diff --git a/tools/data-binding/gradle/wrapper/gradle-wrapper.jar b/tools/data-binding/gradle/wrapper/gradle-wrapper.jar
index 3d0dee6..8c0fb64 100644
--- a/tools/data-binding/gradle/wrapper/gradle-wrapper.jar
+++ b/tools/data-binding/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/tools/data-binding/gradle/wrapper/gradle-wrapper.properties b/tools/data-binding/gradle/wrapper/gradle-wrapper.properties
index 37c1f85..ddbd613 100644
--- a/tools/data-binding/gradle/wrapper/gradle-wrapper.properties
+++ b/tools/data-binding/gradle/wrapper/gradle-wrapper.properties
@@ -14,9 +14,9 @@
 # limitations under the License.
 #
 
-#Tue Nov 18 17:13:29 PST 2014
+#Wed Apr 10 15:27:10 PDT 2013
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=http\://services.gradle.org/distributions/gradle-2.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip
diff --git a/tools/data-binding/gradlePlugin/src/main/kotlin/plugin.kt b/tools/data-binding/gradlePlugin/src/main/kotlin/plugin.kt
index c5a0cf8..535659d1 100644
--- a/tools/data-binding/gradlePlugin/src/main/kotlin/plugin.kt
+++ b/tools/data-binding/gradlePlugin/src/main/kotlin/plugin.kt
@@ -74,14 +74,13 @@
             // TODO read from app
             val variants = arrayListOf("Debug")
             parser = createKParser(project)
-            parser.process()
             log("after eval")
             //processDebugResources
             variants.forEach { variant ->
-                val preTasks = it.getTasksByName("pre${variant}Build", true)
-                preTasks.forEach {
-                    it.doLast (generateAttr)
-                }
+//                val preTasks = it.getTasksByName("pre${variant}Build", true)
+//                preTasks.forEach {
+//                    it.doLast (generateAttr)
+//                }
                 val processResTasks = it.getTasksByName("process${variant}Resources", true)
                 processResTasks.forEach {
                     it.doFirst (generateAttr)
@@ -125,7 +124,8 @@
         sources.forEach({
             log("source: ${it}");
         })
-        val resourceFolders = variantData.mergeResourcesTask.getRawInputFolders()
+        val resourceFolders = arrayListOf(variantData.mergeResourcesTask.getOutputDir())
+        log("MERGE RES OUTPUT ${variantData.mergeResourcesTask.getOutputDir()}")
         //TODO
         val codeGenTargetFolder = variantData.generateRClassTask.getSourceOutputDir()
         val resGenTargetFolder = variantData.generateRClassTask.getResDir()
@@ -214,6 +214,7 @@
     }
 
     fun generateAttr(o: Any?) {
+        parser.processIfNecessary()
         log("generate attr ${o}")
         parser.writeAttrFile()
     }
@@ -227,6 +228,7 @@
     }
 
     fun generateBrFile(o: Any?) {
+        parser.processIfNecessary()
         log("generating BR ${o}")
         parser.writeBrFile()
         parser.writeViewBinderInterfaces()
diff --git a/tools/data-binding/gradlew b/tools/data-binding/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/tools/data-binding/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/tools/data-binding/grammerBuilder/build.gradle b/tools/data-binding/grammerBuilder/build.gradle
index 5b55bf8..122e3d6 100644
--- a/tools/data-binding/grammerBuilder/build.gradle
+++ b/tools/data-binding/grammerBuilder/build.gradle
@@ -26,7 +26,6 @@
 }
 
 dependencies {
-    testCompile 'junit:junit:4.11'
     compile 'com.tunnelvisionlabs:antlr4:4.4'
 }
 
diff --git a/tools/data-binding/grammerBuilder/src/main/java/com/android/databinder/parser/Main.java b/tools/data-binding/grammerBuilder/src/main/java/com/android/databinder/parser/Main.java
index a8406de..ba5c395 100644
--- a/tools/data-binding/grammerBuilder/src/main/java/com/android/databinder/parser/Main.java
+++ b/tools/data-binding/grammerBuilder/src/main/java/com/android/databinder/parser/Main.java
@@ -32,6 +32,7 @@
 //         DataBinderParser parser = new DataBinderParser(tokenStream);
 //         ParseTreeWalker walker = new ParseTreeWalker();
 //         System.out.println(parser.expr().toStringTree(parser));
+        float[] aa = new float[2];
 
     }
 }
diff --git a/tools/data-binding/library/build.gradle b/tools/data-binding/library/build.gradle
index e97c54b..dd49c3f 100644
--- a/tools/data-binding/library/build.gradle
+++ b/tools/data-binding/library/build.gradle
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (C) 2014 The Android Open Source Project
  *
diff --git a/tools/data-binding/samples/BindingDemo/app/src/main/res/layout/list_item.xml b/tools/data-binding/samples/BindingDemo/app/src/main/res/layout/list_item.xml
index d1db3ac..54d8f1b 100644
--- a/tools/data-binding/samples/BindingDemo/app/src/main/res/layout/list_item.xml
+++ b/tools/data-binding/samples/BindingDemo/app/src/main/res/layout/list_item.xml
@@ -22,16 +22,16 @@
     card_view:cardUseCompatPadding="true"
     card_view:contentPadding="8dp"
     android:orientation="horizontal" android:layout_width="wrap_content"
-    bind_var:user="com.android.example.bindingdemo.vo.User"
-    bind_var:clickListener="android.view.View.OnClickListener"
     android:id="@+id/root"
     android:focusable="true"
     android:gravity="center_vertical"
-    bind:onClickListener="clickListener"
+    bind:onClickListener="{clickListener}"
     android:layout_height="match_parent">
+    <variable name="user" type="com.android.example.bindingdemo.vo.User"/>
+    <variable name="clickListener" type="android.view.View.OnClickListener"/>
     <ImageView
         android:id="@+id/user_photo"
-        bind:backgroundResource="user.photoResource"
+        android:backgroundResource="{user.photoResource}"
         android:scaleType="fitCenter"
         android:layout_width="@dimen/user_photo"
         android:layout_height="@dimen/user_photo" />
@@ -40,7 +40,7 @@
         android:layout_marginLeft="@dimen/user_name_margin_left"
         android:id="@+id/fullname"
         android:gravity="center"
-        bind:text="user.name.substring(0,1).toUpperCase() + &quot;. &quot; + user.lastName"
+        android:text="{user.name.substring(0,1).toUpperCase() + &quot;. &quot; + user.lastName}"
         android:layout_width="wrap_content"
         android:layout_height="match_parent" />
 </android.support.v7.widget.CardView>
\ No newline at end of file
diff --git a/tools/data-binding/samples/BindingDemo/app/src/main/res/layout/main_activity.xml b/tools/data-binding/samples/BindingDemo/app/src/main/res/layout/main_activity.xml
index 8cde9e2a..a2b52d5 100644
--- a/tools/data-binding/samples/BindingDemo/app/src/main/res/layout/main_activity.xml
+++ b/tools/data-binding/samples/BindingDemo/app/src/main/res/layout/main_activity.xml
@@ -16,8 +16,6 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:bind="http://schemas.android.com/apk/res-auto"
-    xmlns:bind_static="http://schemas.android.com/apk/res-auto"
-    xmlns:bind_var="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -29,24 +27,28 @@
     android:id="@+id/activityRoot"
     tools:activity=".MainActivity"
     android:clickable="true"
-
-    bind_static:View="android.view.View"
-    bind_static:Strings="com.android.example.bindingdemo.R.string"
-    bind_static:User="com.android.example.bindingdemo.vo.User"
-    bind_var:activity="com.android.example.bindingdemo.MainActivity"
-    bind:onClickListener="activity.onUnselect">
-
+    android:onClickListener="{activity.onUnselect}">
+    <variable name="activity" type="com.android.example.bindingdemo.MainActivity"/>
+    <!---->
+    <import
+            type="android.view.View"
+            />
+    <!---->
+    <import type="com.android.example.bindingdemo.R.string" alias="Strings"/>
+    <import type="com.android.example.bindingdemo.vo.User"/>
     <TextView
         android:id="@+id/title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        bind:text="activity.getString(Strings.toolkitties, activity.tkAdapter.itemCount)" />
+        android:text="{activity.getString(Strings.toolkitties, activity.tkAdapter.itemCount)}">
+
+    </TextView>
 
     <android.support.v7.widget.RecyclerView
         android:id="@+id/toolkittyList"
         android:layout_width="match_parent"
         android:layout_height="@dimen/list_height"
-        bind:adapter="activity.tkAdapter"
+        bind:adapter="{activity.tkAdapter}"
         ></android.support.v7.widget.RecyclerView>
 
     <View
@@ -57,7 +59,7 @@
         android:id="@+id/selected_card"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        bind:visibility="activity.selected == null ? View.GONE : View.VISIBLE">
+        bind:visibility="{activity.selected == null ? View.INVISIBLE : View.VISIBLE}">
 
         <GridLayout
             android:layout_width="match_parent"
@@ -73,7 +75,7 @@
                 android:layout_row="0"
                 android:layout_rowSpan="2"
                 android:scaleType="fitCenter"
-                bind:backgroundResource="activity.selected.photoResource" />
+                android:backgroundResource="{activity.selected.photoResource}" />
 
             <EditText
                 android:id="@+id/selected_name"
@@ -84,7 +86,7 @@
                 android:layout_row="0"
                 android:background="@android:color/holo_blue_dark"
                 android:gravity="center"
-                bind:text="activity.selected.name" />
+                android:text="{activity.selected.name}" />
 
             <EditText
                 android:id="@+id/selected_lastname"
@@ -95,11 +97,11 @@
                 android:layout_row="1"
                 android:background="@android:color/holo_blue_bright"
                 android:gravity="center"
-                bind:text="activity.selected.lastName" />
+                android:text="{activity.selected.lastName}" />
             <Button
                 android:id="@+id/edit_button"
-                bind:onClickListener="activity.onSave"
-                bind:text="`Save changes to ` + activity.selected.name"
+                bind:onClickListener="{activity.onSave}"
+                android:text="{`Save changes to ` + activity.selected.name}"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_column="1"
@@ -108,8 +110,8 @@
 
             <Button
                 android:id="@+id/delete_button"
-                bind:onClickListener="activity.onDelete"
-                bind:text="activity.getString(activity.selected.group == User.TOOLKITTY ? Strings.became_robot : Strings.became_kitten, activity.selected.name)"
+                bind:onClickListener="{activity.onDelete}"
+                android:text="{activity.getString(activity.selected.group == User.TOOLKITTY ? Strings.became_robot : Strings.became_kitten, activity.selected.name)}"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_column="1"
@@ -125,11 +127,9 @@
         android:id="@+id/robotsTitle"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        bind:text="activity.robotAdapter.itemCount + &quot; Robots &quot;" />
+        android:text="{activity.robotAdapter.itemCount + &quot; Robots &quot;}" />
     <android.support.v7.widget.RecyclerView
         android:id="@+id/robotList"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/list_height"
-        bind:adapter="activity.robotAdapter"
+        android:layout_width="match_parent" bind:adapter="{activity.robotAdapter}"  android:layout_height="@dimen/list_height"
         ></android.support.v7.widget.RecyclerView>
 </LinearLayout>
diff --git a/tools/data-binding/settings.gradle b/tools/data-binding/settings.gradle
index c069a57..5dea8c3 100644
--- a/tools/data-binding/settings.gradle
+++ b/tools/data-binding/settings.gradle
@@ -1,4 +1,6 @@
 include ':library'
 include ':compiler'
 include ':gradlePlugin'
-include ':grammerBuilder'
\ No newline at end of file
+include ':grammerBuilder'
+include ':annotationprocessor'
+include 'xmlGrammer'
diff --git a/tools/data-binding/xmlGrammer/XMLLexer.g4 b/tools/data-binding/xmlGrammer/XMLLexer.g4
new file mode 100644
index 0000000..ea7a23c
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/XMLLexer.g4
@@ -0,0 +1,93 @@
+/*
+ [The "BSD licence"]
+ Copyright (c) 2013 Terence Parr
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/** XML lexer derived from ANTLR v4 ref guide book example */
+lexer grammar XMLLexer;
+
+// Default "mode": Everything OUTSIDE of a tag
+COMMENT     :   '<!--' .*? '-->' ;
+CDATA       :   '<![CDATA[' .*? ']]>' ;
+/** Scarf all DTD stuff, Entity Declarations like <!ENTITY ...>,
+ *  and Notation Declarations <!NOTATION ...>
+ */
+DTD         :   '<!' .*? '>'            -> skip ; 
+EntityRef   :   '&' Name ';' ;
+CharRef     :   '&#' DIGIT+ ';'
+            |   '&#x' HEXDIGIT+ ';'
+            ;
+SEA_WS      :   (' '|'\t'|'\r'? '\n')+ ;
+
+OPEN        :   '<'                     -> pushMode(INSIDE) ;
+XMLDeclOpen :   '<?xml' S               -> pushMode(INSIDE) ;
+SPECIAL_OPEN:   '<?' Name               -> more, pushMode(PROC_INSTR) ;
+
+TEXT        :   ~[<&]+ ;        // match any 16 bit char other than < and &
+
+// ----------------- Everything INSIDE of a tag ---------------------
+mode INSIDE;
+
+CLOSE       :   '>'                     -> popMode ;
+SPECIAL_CLOSE:  '?>'                    -> popMode ; // close <?xml...?>
+SLASH_CLOSE :   '/>'                    -> popMode ;
+SLASH       :   '/' ;
+EQUALS      :   '=' ;
+STRING      :   '"' ~[<"]* '"'
+            |   '\'' ~[<']* '\''
+            ;
+Name        :   NameStartChar NameChar* ;
+S           :   [ \t\r\n]               -> skip ;
+
+fragment
+HEXDIGIT    :   [a-fA-F0-9] ;
+
+fragment
+DIGIT       :   [0-9] ;
+
+fragment
+NameChar    :   NameStartChar
+            |   '-' | '_' | '.' | DIGIT 
+            |   '\u00B7'
+            |   '\u0300'..'\u036F'
+            |   '\u203F'..'\u2040'
+            ;
+
+fragment
+NameStartChar
+            :   [:a-zA-Z]
+            |   '\u2070'..'\u218F' 
+            |   '\u2C00'..'\u2FEF' 
+            |   '\u3001'..'\uD7FF' 
+            |   '\uF900'..'\uFDCF' 
+            |   '\uFDF0'..'\uFFFD'
+            ;
+
+// ----------------- Handle <? ... ?> ---------------------
+mode PROC_INSTR;
+
+PI          :   '?>'                    -> popMode ; // close <?...?>
+IGNORE      :   .                       -> more ;
diff --git a/tools/data-binding/xmlGrammer/XMLParser.g4 b/tools/data-binding/xmlGrammer/XMLParser.g4
new file mode 100644
index 0000000..1b03e2d
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/XMLParser.g4
@@ -0,0 +1,54 @@
+/*
+ [The "BSD licence"]
+ Copyright (c) 2013 Terence Parr
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/** XML parser derived from ANTLR v4 ref guide book example */
+parser grammar XMLParser;
+
+options { tokenVocab=XMLLexer; }
+
+document    :   prolog? misc* element misc*;
+
+prolog      :   XMLDeclOpen attribute* SPECIAL_CLOSE ;
+
+content     :   chardata?
+                ((element | reference | CDATA | PI | COMMENT) chardata?)* ;
+
+element     :   '<' elmName=Name attribute* '>' content '<' '/' Name '>'
+            |   '<' elmName=Name attribute* '/>'
+            ;
+
+reference   :   EntityRef | CharRef ;
+
+attribute   :   attrName=Name '=' attrValue=STRING ; // Our STRING is AttValue in spec
+
+/** ``All text that is not markup constitutes the character data of
+ *  the document.''
+ */
+chardata    :   TEXT | SEA_WS ;
+
+misc        :   COMMENT | PI | SEA_WS ;
diff --git a/tools/data-binding/xmlGrammer/build.gradle b/tools/data-binding/xmlGrammer/build.gradle
new file mode 100644
index 0000000..2489f0e
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/build.gradle
@@ -0,0 +1,42 @@
+apply plugin: 'java'
+apply plugin: 'kotlin'
+apply plugin: 'application'
+apply plugin: 'maven'
+
+sourceCompatibility = 1.5
+mainClassName = "org.antlr.v4.Tool"
+
+
+repositories {
+    mavenCentral()
+}
+
+
+buildscript {
+    repositories {
+        mavenCentral()
+    }
+    dependencies {
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
+    }
+}
+
+
+run {
+////    args "XMLLexer.g4", "-visitor", "-o", "src/main/java-gen/com/android/databinding", "-package", "com.android.databinding", "-lib", "."
+    args "XMLParser.g4", "-visitor", "-o", "src/main/java/com/android/databinding", "-package", "com.android.databinding", "-lib", "."
+}
+
+dependencies {
+    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
+    compile 'com.tunnelvisionlabs:antlr4:4.4'
+}
+
+uploadArchives {
+    repositories {
+        mavenDeployer {
+            repository(url: mavenLocal().url)
+            pom.artifactId = 'xmlGrammer'
+        }
+    }
+}
diff --git a/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLLexer.java b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLLexer.java
new file mode 100644
index 0000000..5d85641
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLLexer.java
@@ -0,0 +1,138 @@
+// Generated from XMLLexer.g4 by ANTLR 4.4
+package com.android.databinding;
+import org.antlr.v4.runtime.Lexer;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.TokenStream;
+import org.antlr.v4.runtime.*;
+import org.antlr.v4.runtime.atn.*;
+import org.antlr.v4.runtime.dfa.DFA;
+import org.antlr.v4.runtime.misc.*;
+
+public class XMLLexer extends Lexer {
+	public static final int
+		COMMENT=1, CDATA=2, DTD=3, EntityRef=4, CharRef=5, SEA_WS=6, OPEN=7, XMLDeclOpen=8, 
+		TEXT=9, CLOSE=10, SPECIAL_CLOSE=11, SLASH_CLOSE=12, SLASH=13, EQUALS=14, 
+		STRING=15, Name=16, S=17, PI=18;
+	public static final int INSIDE = 1;
+	public static final int PROC_INSTR = 2;
+	public static String[] modeNames = {
+		"DEFAULT_MODE", "INSIDE", "PROC_INSTR"
+	};
+
+	public static final String[] tokenNames = {
+		"'\\u0000'", "'\\u0001'", "'\\u0002'", "'\\u0003'", "'\\u0004'", "'\\u0005'", 
+		"'\\u0006'", "'\\u0007'", "'\b'", "'\t'", "'\n'", "'\\u000B'", "'\f'", 
+		"'\r'", "'\\u000E'", "'\\u000F'", "'\\u0010'", "'\\u0011'", "'\\u0012'"
+	};
+	public static final String[] ruleNames = {
+		"COMMENT", "CDATA", "DTD", "EntityRef", "CharRef", "SEA_WS", "OPEN", "XMLDeclOpen", 
+		"SPECIAL_OPEN", "TEXT", "CLOSE", "SPECIAL_CLOSE", "SLASH_CLOSE", "SLASH", 
+		"EQUALS", "STRING", "Name", "S", "HEXDIGIT", "DIGIT", "NameChar", "NameStartChar", 
+		"PI", "IGNORE"
+	};
+
+
+	public XMLLexer(CharStream input) {
+		super(input);
+		_interp = new LexerATNSimulator(this,_ATN);
+	}
+
+	@Override
+	public String getGrammarFileName() { return "XMLLexer.g4"; }
+
+	@Override
+	public String[] getTokenNames() { return tokenNames; }
+
+	@Override
+	public String[] getRuleNames() { return ruleNames; }
+
+	@Override
+	public String getSerializedATN() { return _serializedATN; }
+
+	@Override
+	public String[] getModeNames() { return modeNames; }
+
+	public static final String _serializedATN =
+		"\3\uaf6f\u8320\u479d\ub75c\u4880\u1605\u191c\uab37\2\24\u00e9\b\1\b\1"+
+		"\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4"+
+		"\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t"+
+		"\21\4\22\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t"+
+		"\30\4\31\t\31\3\2\3\2\3\2\3\2\3\2\3\2\7\2<\n\2\f\2\16\2?\13\2\3\2\3\2"+
+		"\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\7\3P\n\3\f\3\16\3"+
+		"S\13\3\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\4\7\4]\n\4\f\4\16\4`\13\4\3\4\3\4"+
+		"\3\4\3\4\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\6\6n\n\6\r\6\16\6o\3\6\3\6\3"+
+		"\6\3\6\3\6\3\6\3\6\6\6y\n\6\r\6\16\6z\3\6\3\6\5\6\177\n\6\3\7\3\7\5\7"+
+		"\u0083\n\7\3\7\6\7\u0086\n\7\r\7\16\7\u0087\3\b\3\b\3\b\3\b\3\t\3\t\3"+
+		"\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\6"+
+		"\13\u00a1\n\13\r\13\16\13\u00a2\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3"+
+		"\16\3\16\3\16\3\16\3\16\3\17\3\17\3\20\3\20\3\21\3\21\7\21\u00b9\n\21"+
+		"\f\21\16\21\u00bc\13\21\3\21\3\21\3\21\7\21\u00c1\n\21\f\21\16\21\u00c4"+
+		"\13\21\3\21\5\21\u00c7\n\21\3\22\3\22\7\22\u00cb\n\22\f\22\16\22\u00ce"+
+		"\13\22\3\23\3\23\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26\3\26\3\26\5\26"+
+		"\u00dc\n\26\3\27\5\27\u00df\n\27\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3"+
+		"\31\3\31\5=Q^\2\2\32\5\2\3\7\2\4\t\2\5\13\2\6\r\2\7\17\2\b\21\2\t\23\2"+
+		"\n\25\2\2\27\2\13\31\2\f\33\2\r\35\2\16\37\2\17!\2\20#\2\21%\2\22\'\2"+
+		"\23)\2\2+\2\2-\2\2/\2\2\61\2\24\63\2\2\5\2\3\4\f\4\2\13\13\"\"\4\2((>"+
+		">\4\2$$>>\4\2))>>\5\2\13\f\17\17\"\"\5\2\62;CHch\3\2\62;\4\2/\60aa\5\2"+
+		"\u00b9\u00b9\u0302\u0371\u2041\u2042\n\2<<C\\c|\u2072\u2191\u2c02\u2ff1"+
+		"\u3003\ud801\uf902\ufdd1\ufdf2\uffff\u00f3\2\5\3\2\2\2\2\7\3\2\2\2\2\t"+
+		"\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2"+
+		"\2\2\25\3\2\2\2\2\27\3\2\2\2\3\31\3\2\2\2\3\33\3\2\2\2\3\35\3\2\2\2\3"+
+		"\37\3\2\2\2\3!\3\2\2\2\3#\3\2\2\2\3%\3\2\2\2\3\'\3\2\2\2\4\61\3\2\2\2"+
+		"\4\63\3\2\2\2\5\65\3\2\2\2\7D\3\2\2\2\tX\3\2\2\2\13e\3\2\2\2\r~\3\2\2"+
+		"\2\17\u0085\3\2\2\2\21\u0089\3\2\2\2\23\u008d\3\2\2\2\25\u0097\3\2\2\2"+
+		"\27\u00a0\3\2\2\2\31\u00a4\3\2\2\2\33\u00a8\3\2\2\2\35\u00ad\3\2\2\2\37"+
+		"\u00b2\3\2\2\2!\u00b4\3\2\2\2#\u00c6\3\2\2\2%\u00c8\3\2\2\2\'\u00cf\3"+
+		"\2\2\2)\u00d3\3\2\2\2+\u00d5\3\2\2\2-\u00db\3\2\2\2/\u00de\3\2\2\2\61"+
+		"\u00e0\3\2\2\2\63\u00e5\3\2\2\2\65\66\7>\2\2\66\67\7#\2\2\678\7/\2\28"+
+		"9\7/\2\29=\3\2\2\2:<\13\2\2\2;:\3\2\2\2<?\3\2\2\2=>\3\2\2\2=;\3\2\2\2"+
+		">@\3\2\2\2?=\3\2\2\2@A\7/\2\2AB\7/\2\2BC\7@\2\2C\6\3\2\2\2DE\7>\2\2EF"+
+		"\7#\2\2FG\7]\2\2GH\7E\2\2HI\7F\2\2IJ\7C\2\2JK\7V\2\2KL\7C\2\2LM\7]\2\2"+
+		"MQ\3\2\2\2NP\13\2\2\2ON\3\2\2\2PS\3\2\2\2QR\3\2\2\2QO\3\2\2\2RT\3\2\2"+
+		"\2SQ\3\2\2\2TU\7_\2\2UV\7_\2\2VW\7@\2\2W\b\3\2\2\2XY\7>\2\2YZ\7#\2\2Z"+
+		"^\3\2\2\2[]\13\2\2\2\\[\3\2\2\2]`\3\2\2\2^_\3\2\2\2^\\\3\2\2\2_a\3\2\2"+
+		"\2`^\3\2\2\2ab\7@\2\2bc\3\2\2\2cd\b\4\2\2d\n\3\2\2\2ef\7(\2\2fg\5%\22"+
+		"\2gh\7=\2\2h\f\3\2\2\2ij\7(\2\2jk\7%\2\2km\3\2\2\2ln\5+\25\2ml\3\2\2\2"+
+		"no\3\2\2\2om\3\2\2\2op\3\2\2\2pq\3\2\2\2qr\7=\2\2r\177\3\2\2\2st\7(\2"+
+		"\2tu\7%\2\2uv\7z\2\2vx\3\2\2\2wy\5)\24\2xw\3\2\2\2yz\3\2\2\2zx\3\2\2\2"+
+		"z{\3\2\2\2{|\3\2\2\2|}\7=\2\2}\177\3\2\2\2~i\3\2\2\2~s\3\2\2\2\177\16"+
+		"\3\2\2\2\u0080\u0086\t\2\2\2\u0081\u0083\7\17\2\2\u0082\u0081\3\2\2\2"+
+		"\u0082\u0083\3\2\2\2\u0083\u0084\3\2\2\2\u0084\u0086\7\f\2\2\u0085\u0080"+
+		"\3\2\2\2\u0085\u0082\3\2\2\2\u0086\u0087\3\2\2\2\u0087\u0085\3\2\2\2\u0087"+
+		"\u0088\3\2\2\2\u0088\20\3\2\2\2\u0089\u008a\7>\2\2\u008a\u008b\3\2\2\2"+
+		"\u008b\u008c\b\b\3\2\u008c\22\3\2\2\2\u008d\u008e\7>\2\2\u008e\u008f\7"+
+		"A\2\2\u008f\u0090\7z\2\2\u0090\u0091\7o\2\2\u0091\u0092\7n\2\2\u0092\u0093"+
+		"\3\2\2\2\u0093\u0094\5\'\23\2\u0094\u0095\3\2\2\2\u0095\u0096\b\t\3\2"+
+		"\u0096\24\3\2\2\2\u0097\u0098\7>\2\2\u0098\u0099\7A\2\2\u0099\u009a\3"+
+		"\2\2\2\u009a\u009b\5%\22\2\u009b\u009c\3\2\2\2\u009c\u009d\b\n\4\2\u009d"+
+		"\u009e\b\n\5\2\u009e\26\3\2\2\2\u009f\u00a1\n\3\2\2\u00a0\u009f\3\2\2"+
+		"\2\u00a1\u00a2\3\2\2\2\u00a2\u00a0\3\2\2\2\u00a2\u00a3\3\2\2\2\u00a3\30"+
+		"\3\2\2\2\u00a4\u00a5\7@\2\2\u00a5\u00a6\3\2\2\2\u00a6\u00a7\b\f\6\2\u00a7"+
+		"\32\3\2\2\2\u00a8\u00a9\7A\2\2\u00a9\u00aa\7@\2\2\u00aa\u00ab\3\2\2\2"+
+		"\u00ab\u00ac\b\r\6\2\u00ac\34\3\2\2\2\u00ad\u00ae\7\61\2\2\u00ae\u00af"+
+		"\7@\2\2\u00af\u00b0\3\2\2\2\u00b0\u00b1\b\16\6\2\u00b1\36\3\2\2\2\u00b2"+
+		"\u00b3\7\61\2\2\u00b3 \3\2\2\2\u00b4\u00b5\7?\2\2\u00b5\"\3\2\2\2\u00b6"+
+		"\u00ba\7$\2\2\u00b7\u00b9\n\4\2\2\u00b8\u00b7\3\2\2\2\u00b9\u00bc\3\2"+
+		"\2\2\u00ba\u00b8\3\2\2\2\u00ba\u00bb\3\2\2\2\u00bb\u00bd\3\2\2\2\u00bc"+
+		"\u00ba\3\2\2\2\u00bd\u00c7\7$\2\2\u00be\u00c2\7)\2\2\u00bf\u00c1\n\5\2"+
+		"\2\u00c0\u00bf\3\2\2\2\u00c1\u00c4\3\2\2\2\u00c2\u00c0\3\2\2\2\u00c2\u00c3"+
+		"\3\2\2\2\u00c3\u00c5\3\2\2\2\u00c4\u00c2\3\2\2\2\u00c5\u00c7\7)\2\2\u00c6"+
+		"\u00b6\3\2\2\2\u00c6\u00be\3\2\2\2\u00c7$\3\2\2\2\u00c8\u00cc\5/\27\2"+
+		"\u00c9\u00cb\5-\26\2\u00ca\u00c9\3\2\2\2\u00cb\u00ce\3\2\2\2\u00cc\u00ca"+
+		"\3\2\2\2\u00cc\u00cd\3\2\2\2\u00cd&\3\2\2\2\u00ce\u00cc\3\2\2\2\u00cf"+
+		"\u00d0\t\6\2\2\u00d0\u00d1\3\2\2\2\u00d1\u00d2\b\23\2\2\u00d2(\3\2\2\2"+
+		"\u00d3\u00d4\t\7\2\2\u00d4*\3\2\2\2\u00d5\u00d6\t\b\2\2\u00d6,\3\2\2\2"+
+		"\u00d7\u00dc\5/\27\2\u00d8\u00dc\t\t\2\2\u00d9\u00dc\5+\25\2\u00da\u00dc"+
+		"\t\n\2\2\u00db\u00d7\3\2\2\2\u00db\u00d8\3\2\2\2\u00db\u00d9\3\2\2\2\u00db"+
+		"\u00da\3\2\2\2\u00dc.\3\2\2\2\u00dd\u00df\t\13\2\2\u00de\u00dd\3\2\2\2"+
+		"\u00df\60\3\2\2\2\u00e0\u00e1\7A\2\2\u00e1\u00e2\7@\2\2\u00e2\u00e3\3"+
+		"\2\2\2\u00e3\u00e4\b\30\6\2\u00e4\62\3\2\2\2\u00e5\u00e6\13\2\2\2\u00e6"+
+		"\u00e7\3\2\2\2\u00e7\u00e8\b\31\4\2\u00e8\64\3\2\2\2\25\2\3\4=Q^oz~\u0082"+
+		"\u0085\u0087\u00a2\u00ba\u00c2\u00c6\u00cc\u00db\u00de\7\b\2\2\7\3\2\5"+
+		"\2\2\7\4\2\6\2\2";
+	public static final ATN _ATN =
+		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
+	static {
+	}
+}
\ No newline at end of file
diff --git a/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLLexer.tokens b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLLexer.tokens
new file mode 100644
index 0000000..cd122a4
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLLexer.tokens
@@ -0,0 +1,23 @@
+OPEN=7
+CDATA=2
+SLASH=13
+CharRef=5
+SEA_WS=6
+SPECIAL_CLOSE=11
+CLOSE=10
+DTD=3
+Name=16
+EQUALS=14
+PI=18
+S=17
+SLASH_CLOSE=12
+TEXT=9
+COMMENT=1
+XMLDeclOpen=8
+EntityRef=4
+STRING=15
+'='=14
+'/'=13
+'<'=7
+'/>'=12
+'>'=10
diff --git a/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParser.java b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParser.java
new file mode 100644
index 0000000..a324494
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParser.java
@@ -0,0 +1,660 @@
+// Generated from XMLParser.g4 by ANTLR 4.4
+package com.android.databinding;
+import org.antlr.v4.runtime.atn.*;
+import org.antlr.v4.runtime.dfa.DFA;
+import org.antlr.v4.runtime.*;
+import org.antlr.v4.runtime.misc.*;
+import org.antlr.v4.runtime.tree.*;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+public class XMLParser extends Parser {
+	public static final int
+		OPEN=7, CDATA=2, SLASH=13, CharRef=5, SEA_WS=6, SPECIAL_CLOSE=11, CLOSE=10, 
+		DTD=3, Name=16, EQUALS=14, PI=18, S=17, SLASH_CLOSE=12, TEXT=9, COMMENT=1, 
+		XMLDeclOpen=8, EntityRef=4, STRING=15;
+	public static final String[] tokenNames = {
+		"<INVALID>", "COMMENT", "CDATA", "DTD", "EntityRef", "CharRef", "SEA_WS", 
+		"'<'", "XMLDeclOpen", "TEXT", "'>'", "SPECIAL_CLOSE", "'/>'", "'/'", "'='", 
+		"STRING", "Name", "S", "PI"
+	};
+	public static final int
+		RULE_document = 0, RULE_prolog = 1, RULE_content = 2, RULE_element = 3, 
+		RULE_reference = 4, RULE_attribute = 5, RULE_chardata = 6, RULE_misc = 7;
+	public static final String[] ruleNames = {
+		"document", "prolog", "content", "element", "reference", "attribute", 
+		"chardata", "misc"
+	};
+
+	@Override
+	public String getGrammarFileName() { return "XMLParser.g4"; }
+
+	@Override
+	public String[] getTokenNames() { return tokenNames; }
+
+	@Override
+	public String[] getRuleNames() { return ruleNames; }
+
+	@Override
+	public String getSerializedATN() { return _serializedATN; }
+
+	public XMLParser(TokenStream input) {
+		super(input);
+		_interp = new ParserATNSimulator(this,_ATN);
+	}
+	public static class DocumentContext extends ParserRuleContext {
+		public ElementContext element() {
+			return getRuleContext(ElementContext.class,0);
+		}
+		public List<? extends MiscContext> misc() {
+			return getRuleContexts(MiscContext.class);
+		}
+		public PrologContext prolog() {
+			return getRuleContext(PrologContext.class,0);
+		}
+		public MiscContext misc(int i) {
+			return getRuleContext(MiscContext.class,i);
+		}
+		public DocumentContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_document; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).enterDocument(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitDocument(this);
+		}
+		@Override
+		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
+			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitDocument(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	@RuleVersion(0)
+	public final DocumentContext document() throws RecognitionException {
+		DocumentContext _localctx = new DocumentContext(_ctx, getState());
+		enterRule(_localctx, 0, RULE_document);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(17);
+			_la = _input.LA(1);
+			if (_la==XMLDeclOpen) {
+				{
+				setState(16); prolog();
+				}
+			}
+
+			setState(22);
+			_errHandler.sync(this);
+			_la = _input.LA(1);
+			while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << COMMENT) | (1L << SEA_WS) | (1L << PI))) != 0)) {
+				{
+				{
+				setState(19); misc();
+				}
+				}
+				setState(24);
+				_errHandler.sync(this);
+				_la = _input.LA(1);
+			}
+			setState(25); element();
+			setState(29);
+			_errHandler.sync(this);
+			_la = _input.LA(1);
+			while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << COMMENT) | (1L << SEA_WS) | (1L << PI))) != 0)) {
+				{
+				{
+				setState(26); misc();
+				}
+				}
+				setState(31);
+				_errHandler.sync(this);
+				_la = _input.LA(1);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class PrologContext extends ParserRuleContext {
+		public TerminalNode SPECIAL_CLOSE() { return getToken(XMLParser.SPECIAL_CLOSE, 0); }
+		public List<? extends AttributeContext> attribute() {
+			return getRuleContexts(AttributeContext.class);
+		}
+		public AttributeContext attribute(int i) {
+			return getRuleContext(AttributeContext.class,i);
+		}
+		public TerminalNode XMLDeclOpen() { return getToken(XMLParser.XMLDeclOpen, 0); }
+		public PrologContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_prolog; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).enterProlog(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitProlog(this);
+		}
+		@Override
+		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
+			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitProlog(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	@RuleVersion(0)
+	public final PrologContext prolog() throws RecognitionException {
+		PrologContext _localctx = new PrologContext(_ctx, getState());
+		enterRule(_localctx, 2, RULE_prolog);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(32); match(XMLDeclOpen);
+			setState(36);
+			_errHandler.sync(this);
+			_la = _input.LA(1);
+			while (_la==Name) {
+				{
+				{
+				setState(33); attribute();
+				}
+				}
+				setState(38);
+				_errHandler.sync(this);
+				_la = _input.LA(1);
+			}
+			setState(39); match(SPECIAL_CLOSE);
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class ContentContext extends ParserRuleContext {
+		public List<? extends TerminalNode> PI() { return getTokens(XMLParser.PI); }
+		public List<? extends TerminalNode> CDATA() { return getTokens(XMLParser.CDATA); }
+		public List<? extends ElementContext> element() {
+			return getRuleContexts(ElementContext.class);
+		}
+		public TerminalNode PI(int i) {
+			return getToken(XMLParser.PI, i);
+		}
+		public ElementContext element(int i) {
+			return getRuleContext(ElementContext.class,i);
+		}
+		public TerminalNode COMMENT(int i) {
+			return getToken(XMLParser.COMMENT, i);
+		}
+		public TerminalNode CDATA(int i) {
+			return getToken(XMLParser.CDATA, i);
+		}
+		public ReferenceContext reference(int i) {
+			return getRuleContext(ReferenceContext.class,i);
+		}
+		public List<? extends TerminalNode> COMMENT() { return getTokens(XMLParser.COMMENT); }
+		public ChardataContext chardata(int i) {
+			return getRuleContext(ChardataContext.class,i);
+		}
+		public List<? extends ChardataContext> chardata() {
+			return getRuleContexts(ChardataContext.class);
+		}
+		public List<? extends ReferenceContext> reference() {
+			return getRuleContexts(ReferenceContext.class);
+		}
+		public ContentContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_content; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).enterContent(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitContent(this);
+		}
+		@Override
+		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
+			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitContent(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	@RuleVersion(0)
+	public final ContentContext content() throws RecognitionException {
+		ContentContext _localctx = new ContentContext(_ctx, getState());
+		enterRule(_localctx, 4, RULE_content);
+		int _la;
+		try {
+			int _alt;
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(42);
+			_la = _input.LA(1);
+			if (_la==SEA_WS || _la==TEXT) {
+				{
+				setState(41); chardata();
+				}
+			}
+
+			setState(56);
+			_errHandler.sync(this);
+			_alt = getInterpreter().adaptivePredict(_input,7,_ctx);
+			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
+				if ( _alt==1 ) {
+					{
+					{
+					setState(49);
+					switch (_input.LA(1)) {
+					case OPEN:
+						{
+						setState(44); element();
+						}
+						break;
+					case EntityRef:
+					case CharRef:
+						{
+						setState(45); reference();
+						}
+						break;
+					case CDATA:
+						{
+						setState(46); match(CDATA);
+						}
+						break;
+					case PI:
+						{
+						setState(47); match(PI);
+						}
+						break;
+					case COMMENT:
+						{
+						setState(48); match(COMMENT);
+						}
+						break;
+					default:
+						throw new NoViableAltException(this);
+					}
+					setState(52);
+					_la = _input.LA(1);
+					if (_la==SEA_WS || _la==TEXT) {
+						{
+						setState(51); chardata();
+						}
+					}
+
+					}
+					} 
+				}
+				setState(58);
+				_errHandler.sync(this);
+				_alt = getInterpreter().adaptivePredict(_input,7,_ctx);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class ElementContext extends ParserRuleContext {
+		public Token elmName;
+		public List<? extends AttributeContext> attribute() {
+			return getRuleContexts(AttributeContext.class);
+		}
+		public AttributeContext attribute(int i) {
+			return getRuleContext(AttributeContext.class,i);
+		}
+		public TerminalNode Name(int i) {
+			return getToken(XMLParser.Name, i);
+		}
+		public List<? extends TerminalNode> Name() { return getTokens(XMLParser.Name); }
+		public ContentContext content() {
+			return getRuleContext(ContentContext.class,0);
+		}
+		public ElementContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_element; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).enterElement(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitElement(this);
+		}
+		@Override
+		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
+			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitElement(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	@RuleVersion(0)
+	public final ElementContext element() throws RecognitionException {
+		ElementContext _localctx = new ElementContext(_ctx, getState());
+		enterRule(_localctx, 6, RULE_element);
+		int _la;
+		try {
+			setState(83);
+			switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) {
+			case 1:
+				enterOuterAlt(_localctx, 1);
+				{
+				setState(59); match(OPEN);
+				setState(60); _localctx.elmName = match(Name);
+				setState(64);
+				_errHandler.sync(this);
+				_la = _input.LA(1);
+				while (_la==Name) {
+					{
+					{
+					setState(61); attribute();
+					}
+					}
+					setState(66);
+					_errHandler.sync(this);
+					_la = _input.LA(1);
+				}
+				setState(67); match(CLOSE);
+				setState(68); content();
+				setState(69); match(OPEN);
+				setState(70); match(SLASH);
+				setState(71); match(Name);
+				setState(72); match(CLOSE);
+				}
+				break;
+
+			case 2:
+				enterOuterAlt(_localctx, 2);
+				{
+				setState(74); match(OPEN);
+				setState(75); _localctx.elmName = match(Name);
+				setState(79);
+				_errHandler.sync(this);
+				_la = _input.LA(1);
+				while (_la==Name) {
+					{
+					{
+					setState(76); attribute();
+					}
+					}
+					setState(81);
+					_errHandler.sync(this);
+					_la = _input.LA(1);
+				}
+				setState(82); match(SLASH_CLOSE);
+				}
+				break;
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class ReferenceContext extends ParserRuleContext {
+		public TerminalNode CharRef() { return getToken(XMLParser.CharRef, 0); }
+		public TerminalNode EntityRef() { return getToken(XMLParser.EntityRef, 0); }
+		public ReferenceContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_reference; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).enterReference(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitReference(this);
+		}
+		@Override
+		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
+			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitReference(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	@RuleVersion(0)
+	public final ReferenceContext reference() throws RecognitionException {
+		ReferenceContext _localctx = new ReferenceContext(_ctx, getState());
+		enterRule(_localctx, 8, RULE_reference);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(85);
+			_la = _input.LA(1);
+			if ( !(_la==EntityRef || _la==CharRef) ) {
+			_errHandler.recoverInline(this);
+			}
+			consume();
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class AttributeContext extends ParserRuleContext {
+		public Token attrName;
+		public Token attrValue;
+		public TerminalNode Name() { return getToken(XMLParser.Name, 0); }
+		public TerminalNode STRING() { return getToken(XMLParser.STRING, 0); }
+		public AttributeContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_attribute; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).enterAttribute(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitAttribute(this);
+		}
+		@Override
+		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
+			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitAttribute(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	@RuleVersion(0)
+	public final AttributeContext attribute() throws RecognitionException {
+		AttributeContext _localctx = new AttributeContext(_ctx, getState());
+		enterRule(_localctx, 10, RULE_attribute);
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(87); _localctx.attrName = match(Name);
+			setState(88); match(EQUALS);
+			setState(89); _localctx.attrValue = match(STRING);
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class ChardataContext extends ParserRuleContext {
+		public TerminalNode SEA_WS() { return getToken(XMLParser.SEA_WS, 0); }
+		public TerminalNode TEXT() { return getToken(XMLParser.TEXT, 0); }
+		public ChardataContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_chardata; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).enterChardata(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitChardata(this);
+		}
+		@Override
+		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
+			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitChardata(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	@RuleVersion(0)
+	public final ChardataContext chardata() throws RecognitionException {
+		ChardataContext _localctx = new ChardataContext(_ctx, getState());
+		enterRule(_localctx, 12, RULE_chardata);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(91);
+			_la = _input.LA(1);
+			if ( !(_la==SEA_WS || _la==TEXT) ) {
+			_errHandler.recoverInline(this);
+			}
+			consume();
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class MiscContext extends ParserRuleContext {
+		public TerminalNode SEA_WS() { return getToken(XMLParser.SEA_WS, 0); }
+		public TerminalNode PI() { return getToken(XMLParser.PI, 0); }
+		public TerminalNode COMMENT() { return getToken(XMLParser.COMMENT, 0); }
+		public MiscContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_misc; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).enterMisc(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitMisc(this);
+		}
+		@Override
+		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
+			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitMisc(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	@RuleVersion(0)
+	public final MiscContext misc() throws RecognitionException {
+		MiscContext _localctx = new MiscContext(_ctx, getState());
+		enterRule(_localctx, 14, RULE_misc);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(93);
+			_la = _input.LA(1);
+			if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << COMMENT) | (1L << SEA_WS) | (1L << PI))) != 0)) ) {
+			_errHandler.recoverInline(this);
+			}
+			consume();
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static final String _serializedATN =
+		"\3\uaf6f\u8320\u479d\ub75c\u4880\u1605\u191c\uab37\3\24b\4\2\t\2\4\3\t"+
+		"\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\3\2\5\2\24\n\2\3\2"+
+		"\7\2\27\n\2\f\2\16\2\32\13\2\3\2\3\2\7\2\36\n\2\f\2\16\2!\13\2\3\3\3\3"+
+		"\7\3%\n\3\f\3\16\3(\13\3\3\3\3\3\3\4\5\4-\n\4\3\4\3\4\3\4\3\4\3\4\5\4"+
+		"\64\n\4\3\4\5\4\67\n\4\7\49\n\4\f\4\16\4<\13\4\3\5\3\5\3\5\7\5A\n\5\f"+
+		"\5\16\5D\13\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\7\5P\n\5\f\5\16"+
+		"\5S\13\5\3\5\5\5V\n\5\3\6\3\6\3\7\3\7\3\7\3\7\3\b\3\b\3\t\3\t\3\t\2\2"+
+		"\2\n\2\2\4\2\6\2\b\2\n\2\f\2\16\2\20\2\2\5\3\2\6\7\4\2\b\b\13\13\5\2\3"+
+		"\3\b\b\24\24g\2\23\3\2\2\2\4\"\3\2\2\2\6,\3\2\2\2\bU\3\2\2\2\nW\3\2\2"+
+		"\2\fY\3\2\2\2\16]\3\2\2\2\20_\3\2\2\2\22\24\5\4\3\2\23\22\3\2\2\2\23\24"+
+		"\3\2\2\2\24\30\3\2\2\2\25\27\5\20\t\2\26\25\3\2\2\2\27\32\3\2\2\2\30\26"+
+		"\3\2\2\2\30\31\3\2\2\2\31\33\3\2\2\2\32\30\3\2\2\2\33\37\5\b\5\2\34\36"+
+		"\5\20\t\2\35\34\3\2\2\2\36!\3\2\2\2\37\35\3\2\2\2\37 \3\2\2\2 \3\3\2\2"+
+		"\2!\37\3\2\2\2\"&\7\n\2\2#%\5\f\7\2$#\3\2\2\2%(\3\2\2\2&$\3\2\2\2&\'\3"+
+		"\2\2\2\')\3\2\2\2(&\3\2\2\2)*\7\r\2\2*\5\3\2\2\2+-\5\16\b\2,+\3\2\2\2"+
+		",-\3\2\2\2-:\3\2\2\2.\64\5\b\5\2/\64\5\n\6\2\60\64\7\4\2\2\61\64\7\24"+
+		"\2\2\62\64\7\3\2\2\63.\3\2\2\2\63/\3\2\2\2\63\60\3\2\2\2\63\61\3\2\2\2"+
+		"\63\62\3\2\2\2\64\66\3\2\2\2\65\67\5\16\b\2\66\65\3\2\2\2\66\67\3\2\2"+
+		"\2\679\3\2\2\28\63\3\2\2\29<\3\2\2\2:8\3\2\2\2:;\3\2\2\2;\7\3\2\2\2<:"+
+		"\3\2\2\2=>\7\t\2\2>B\7\22\2\2?A\5\f\7\2@?\3\2\2\2AD\3\2\2\2B@\3\2\2\2"+
+		"BC\3\2\2\2CE\3\2\2\2DB\3\2\2\2EF\7\f\2\2FG\5\6\4\2GH\7\t\2\2HI\7\17\2"+
+		"\2IJ\7\22\2\2JK\7\f\2\2KV\3\2\2\2LM\7\t\2\2MQ\7\22\2\2NP\5\f\7\2ON\3\2"+
+		"\2\2PS\3\2\2\2QO\3\2\2\2QR\3\2\2\2RT\3\2\2\2SQ\3\2\2\2TV\7\16\2\2U=\3"+
+		"\2\2\2UL\3\2\2\2V\t\3\2\2\2WX\t\2\2\2X\13\3\2\2\2YZ\7\22\2\2Z[\7\20\2"+
+		"\2[\\\7\21\2\2\\\r\3\2\2\2]^\t\3\2\2^\17\3\2\2\2_`\t\4\2\2`\21\3\2\2\2"+
+		"\r\23\30\37&,\63\66:BQU";
+	public static final ATN _ATN =
+		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
+	static {
+	}
+}
\ No newline at end of file
diff --git a/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParser.tokens b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParser.tokens
new file mode 100644
index 0000000..b1423a1
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParser.tokens
@@ -0,0 +1,23 @@
+OPEN=7
+CDATA=2
+SLASH=13
+CharRef=5
+SEA_WS=6
+SPECIAL_CLOSE=11
+CLOSE=10
+DTD=3
+Name=16
+EQUALS=14
+PI=18
+SLASH_CLOSE=12
+S=17
+TEXT=9
+XMLDeclOpen=8
+COMMENT=1
+EntityRef=4
+STRING=15
+'='=14
+'<'=7
+'/'=13
+'/>'=12
+'>'=10
diff --git a/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseListener.java b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseListener.java
new file mode 100644
index 0000000..9c43842
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseListener.java
@@ -0,0 +1,144 @@
+// Generated from XMLParser.g4 by ANTLR 4.4
+package com.android.databinding;
+
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.misc.NotNull;
+import org.antlr.v4.runtime.tree.ErrorNode;
+import org.antlr.v4.runtime.tree.TerminalNode;
+
+/**
+ * This class provides an empty implementation of {@link XMLParserListener},
+ * which can be extended to create a listener which only needs to handle a subset
+ * of the available methods.
+ */
+public class XMLParserBaseListener implements XMLParserListener {
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterContent(@NotNull XMLParser.ContentContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitContent(@NotNull XMLParser.ContentContext ctx) { }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterElement(@NotNull XMLParser.ElementContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitElement(@NotNull XMLParser.ElementContext ctx) { }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterProlog(@NotNull XMLParser.PrologContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitProlog(@NotNull XMLParser.PrologContext ctx) { }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterDocument(@NotNull XMLParser.DocumentContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitDocument(@NotNull XMLParser.DocumentContext ctx) { }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterAttribute(@NotNull XMLParser.AttributeContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitAttribute(@NotNull XMLParser.AttributeContext ctx) { }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterChardata(@NotNull XMLParser.ChardataContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitChardata(@NotNull XMLParser.ChardataContext ctx) { }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterReference(@NotNull XMLParser.ReferenceContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitReference(@NotNull XMLParser.ReferenceContext ctx) { }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterMisc(@NotNull XMLParser.MiscContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitMisc(@NotNull XMLParser.MiscContext ctx) { }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterEveryRule(@NotNull ParserRuleContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitEveryRule(@NotNull ParserRuleContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void visitTerminal(@NotNull TerminalNode node) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void visitErrorNode(@NotNull ErrorNode node) { }
+}
\ No newline at end of file
diff --git a/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseVisitor.java b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseVisitor.java
new file mode 100644
index 0000000..91d18e7
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseVisitor.java
@@ -0,0 +1,79 @@
+// Generated from XMLParser.g4 by ANTLR 4.4
+package com.android.databinding;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.misc.NotNull;
+import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
+
+/**
+ * This class provides an empty implementation of {@link XMLParserVisitor},
+ * which can be extended to create a visitor which only needs to handle a subset
+ * of the available methods.
+ *
+ * @param <Result> The return type of the visit operation. Use {@link Void} for
+ * operations with no return type.
+ */
+public class XMLParserBaseVisitor<Result> extends AbstractParseTreeVisitor<Result> implements XMLParserVisitor<Result> {
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public Result visitContent(@NotNull XMLParser.ContentContext ctx) { return visitChildren(ctx); }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public Result visitElement(@NotNull XMLParser.ElementContext ctx) { return visitChildren(ctx); }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public Result visitProlog(@NotNull XMLParser.PrologContext ctx) { return visitChildren(ctx); }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public Result visitDocument(@NotNull XMLParser.DocumentContext ctx) { return visitChildren(ctx); }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public Result visitAttribute(@NotNull XMLParser.AttributeContext ctx) { return visitChildren(ctx); }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public Result visitChardata(@NotNull XMLParser.ChardataContext ctx) { return visitChildren(ctx); }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public Result visitReference(@NotNull XMLParser.ReferenceContext ctx) { return visitChildren(ctx); }
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public Result visitMisc(@NotNull XMLParser.MiscContext ctx) { return visitChildren(ctx); }
+}
\ No newline at end of file
diff --git a/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserListener.java b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserListener.java
new file mode 100644
index 0000000..b5499a6
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserListener.java
@@ -0,0 +1,99 @@
+// Generated from XMLParser.g4 by ANTLR 4.4
+package com.android.databinding;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.misc.NotNull;
+import org.antlr.v4.runtime.tree.ParseTreeListener;
+
+/**
+ * This interface defines a complete listener for a parse tree produced by
+ * {@link XMLParser}.
+ */
+public interface XMLParserListener extends ParseTreeListener {
+	/**
+	 * Enter a parse tree produced by {@link XMLParser#content}.
+	 * @param ctx the parse tree
+	 */
+	void enterContent(@NotNull XMLParser.ContentContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link XMLParser#content}.
+	 * @param ctx the parse tree
+	 */
+	void exitContent(@NotNull XMLParser.ContentContext ctx);
+
+	/**
+	 * Enter a parse tree produced by {@link XMLParser#element}.
+	 * @param ctx the parse tree
+	 */
+	void enterElement(@NotNull XMLParser.ElementContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link XMLParser#element}.
+	 * @param ctx the parse tree
+	 */
+	void exitElement(@NotNull XMLParser.ElementContext ctx);
+
+	/**
+	 * Enter a parse tree produced by {@link XMLParser#prolog}.
+	 * @param ctx the parse tree
+	 */
+	void enterProlog(@NotNull XMLParser.PrologContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link XMLParser#prolog}.
+	 * @param ctx the parse tree
+	 */
+	void exitProlog(@NotNull XMLParser.PrologContext ctx);
+
+	/**
+	 * Enter a parse tree produced by {@link XMLParser#document}.
+	 * @param ctx the parse tree
+	 */
+	void enterDocument(@NotNull XMLParser.DocumentContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link XMLParser#document}.
+	 * @param ctx the parse tree
+	 */
+	void exitDocument(@NotNull XMLParser.DocumentContext ctx);
+
+	/**
+	 * Enter a parse tree produced by {@link XMLParser#attribute}.
+	 * @param ctx the parse tree
+	 */
+	void enterAttribute(@NotNull XMLParser.AttributeContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link XMLParser#attribute}.
+	 * @param ctx the parse tree
+	 */
+	void exitAttribute(@NotNull XMLParser.AttributeContext ctx);
+
+	/**
+	 * Enter a parse tree produced by {@link XMLParser#chardata}.
+	 * @param ctx the parse tree
+	 */
+	void enterChardata(@NotNull XMLParser.ChardataContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link XMLParser#chardata}.
+	 * @param ctx the parse tree
+	 */
+	void exitChardata(@NotNull XMLParser.ChardataContext ctx);
+
+	/**
+	 * Enter a parse tree produced by {@link XMLParser#reference}.
+	 * @param ctx the parse tree
+	 */
+	void enterReference(@NotNull XMLParser.ReferenceContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link XMLParser#reference}.
+	 * @param ctx the parse tree
+	 */
+	void exitReference(@NotNull XMLParser.ReferenceContext ctx);
+
+	/**
+	 * Enter a parse tree produced by {@link XMLParser#misc}.
+	 * @param ctx the parse tree
+	 */
+	void enterMisc(@NotNull XMLParser.MiscContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link XMLParser#misc}.
+	 * @param ctx the parse tree
+	 */
+	void exitMisc(@NotNull XMLParser.MiscContext ctx);
+}
\ No newline at end of file
diff --git a/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserVisitor.java b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserVisitor.java
new file mode 100644
index 0000000..58a65f40
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/src/main/java/com/android/databinding/XMLParserVisitor.java
@@ -0,0 +1,70 @@
+// Generated from XMLParser.g4 by ANTLR 4.4
+package com.android.databinding;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.misc.NotNull;
+import org.antlr.v4.runtime.tree.ParseTreeVisitor;
+
+/**
+ * This interface defines a complete generic visitor for a parse tree produced
+ * by {@link XMLParser}.
+ *
+ * @param <Result> The return type of the visit operation. Use {@link Void} for
+ * operations with no return type.
+ */
+public interface XMLParserVisitor<Result> extends ParseTreeVisitor<Result> {
+	/**
+	 * Visit a parse tree produced by {@link XMLParser#content}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	Result visitContent(@NotNull XMLParser.ContentContext ctx);
+
+	/**
+	 * Visit a parse tree produced by {@link XMLParser#element}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	Result visitElement(@NotNull XMLParser.ElementContext ctx);
+
+	/**
+	 * Visit a parse tree produced by {@link XMLParser#prolog}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	Result visitProlog(@NotNull XMLParser.PrologContext ctx);
+
+	/**
+	 * Visit a parse tree produced by {@link XMLParser#document}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	Result visitDocument(@NotNull XMLParser.DocumentContext ctx);
+
+	/**
+	 * Visit a parse tree produced by {@link XMLParser#attribute}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	Result visitAttribute(@NotNull XMLParser.AttributeContext ctx);
+
+	/**
+	 * Visit a parse tree produced by {@link XMLParser#chardata}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	Result visitChardata(@NotNull XMLParser.ChardataContext ctx);
+
+	/**
+	 * Visit a parse tree produced by {@link XMLParser#reference}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	Result visitReference(@NotNull XMLParser.ReferenceContext ctx);
+
+	/**
+	 * Visit a parse tree produced by {@link XMLParser#misc}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	Result visitMisc(@NotNull XMLParser.MiscContext ctx);
+}
\ No newline at end of file
diff --git a/tools/data-binding/xmlGrammer/src/main/kotlin/xmlEditorTest.kt b/tools/data-binding/xmlGrammer/src/main/kotlin/xmlEditorTest.kt
new file mode 100644
index 0000000..2f9d0da
--- /dev/null
+++ b/tools/data-binding/xmlGrammer/src/main/kotlin/xmlEditorTest.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.databinding
+
+import java.io.File
+import org.antlr.v4.runtime.ANTLRInputStream
+import org.antlr.v4.runtime.CommonTokenStream
+import java.io.FileReader
+import org.antlr.v4.runtime.Token
+import java.util.Comparator
+import kotlin.properties.Delegates
+
+fun main(vararg args : String) {
+    val f = File("/Volumes/ssd/src/data-binding/KDataBinder/samples/BindingDemo/app/src/main/res/layout/main_activity.xml")
+    antlrTest(f);
+}
+
+fun log(f : () -> String) {
+    System.out.println("LOG: ${f()}");
+}
+
+fun antlrTest(f: File) : String? {
+    val inputStream = ANTLRInputStream(FileReader(f))
+    val lexer = XMLLexer(inputStream)
+    val tokenStream = CommonTokenStream(lexer)
+    val parser = XMLParser(tokenStream)
+    val expr = parser.document()
+    log{"exp tree: ${expr.toStringTree(parser)}"}
+    val reservedElementNames = arrayListOf("variable", "import")
+    val visitor = object : XMLParserBaseVisitor<MutableList<Pair<Position, Position>>>() {
+        override fun visitAttribute(ctx: XMLParser.AttributeContext): MutableList<Pair<Position, Position>>? {
+            log{"attr:${ctx.attrName.getText()} ${ctx.attrValue.getText()}"}
+            if (ctx.attrName.getText().startsWith("bind:")) {
+
+                return arrayListOf(Pair(ctx.getStart().toPosition(), ctx.getStop().toEndPosition()))
+            } else if (ctx.attrValue.getText().startsWith("\"{") && ctx.attrValue.getText().endsWith("}\"")) {
+                return arrayListOf(Pair(ctx.getStart().toPosition(), ctx.getStop().toEndPosition()))
+            }
+
+            //log{"visiting attr: ${ctx.getText()} at location ${ctx.getStart().toS()} ${ctx.getStop().toS()}"}
+            return super<XMLParserBaseVisitor>.visitAttribute(ctx)
+        }
+
+        override fun visitElement(ctx: XMLParser.ElementContext): MutableList<Pair<Position, Position>>? {
+            log{"elm ${ctx.elmName.getText()} || ${ctx.Name()}"}
+            if (reservedElementNames.contains(ctx.elmName?.getText()) || ctx.elmName.getText().startsWith("bind:")) {
+                return arrayListOf(Pair(ctx.getStart().toPosition(), ctx.getStop().toEndPosition()))
+            }
+            return super< XMLParserBaseVisitor>.visitElement(ctx)
+        }
+
+        override fun defaultResult(): MutableList<Pair<Position, Position>>? = arrayListOf()
+
+        override fun aggregateResult(aggregate: MutableList<Pair<Position, Position>>?, nextResult: MutableList<Pair<Position, Position>>?): MutableList<Pair<Position, Position>>? {
+            return if (aggregate == null) {
+                return nextResult 
+            } else if (nextResult == null) {
+                return aggregate
+            } else {
+                aggregate.addAll(nextResult)
+                return aggregate
+            }
+        }
+    }
+    val parsedExpr = expr.accept(visitor)
+    if (parsedExpr.size() == 0) {
+        return null//nothing to strip
+    }
+    log {"result ${parsedExpr.joinToString("\n-> ")}"}
+    parsedExpr.forEach {
+        log {"${it.first.line} ${it.first.charIndex}"}
+    }
+    val out = StringBuilder()
+    val lines = f.readLines("utf-8")
+    lines.forEach { out.appendln(it) }
+
+    val sorted = parsedExpr.sortBy(object : Comparator<Pair<Position, Position>> {
+        override fun compare(o1: Pair<Position, Position>, o2: Pair<Position, Position>): Int {
+            val lineCmp = o1.first.line.compareTo(o2.first.charIndex)
+            if (lineCmp != 0) {
+                return lineCmp
+            }
+            return o1.first.line.compareTo(o2.first.charIndex)
+        }
+    })
+
+    var lineStarts = arrayListOf(0)
+
+    lines.withIndices().forEach {
+        if (it.first > 0) {
+            lineStarts.add(lineStarts[it.first - 1] + lines[it.first - 1].length() + 1)
+        }
+    }
+
+    val seperator = System.lineSeparator().charAt(0)
+
+    sorted.forEach {
+        val posStart = lineStarts[it.first.line] + it.first.charIndex
+        val posEnd = lineStarts[it.second.line] + it.second.charIndex
+        for( i in posStart..(posEnd - 1)) {
+            if (out.charAt(i) != seperator) {
+                out.setCharAt(i, ' ')
+            }
+        }
+    }
+
+    return out.toString()
+}
+
+
+fun org.antlr.v4.runtime.Token.toS() : String = "[L:${getLine()} CH:${getCharPositionInLine()}]"
+
+fun org.antlr.v4.runtime.Token.toPosition() : Position = Position(getLine() -1 , getCharPositionInLine())
+
+fun org.antlr.v4.runtime.Token.toEndPosition() : Position = Position(getLine() - 1 , getCharPositionInLine() + getText().size)
+
+data class Position(var line : Int, var charIndex : Int) {
+}