summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/build.gradle1
-rw-r--r--compiler/src/main/kotlin/com/android/databinding/ext/node_ext.kt19
-rw-r--r--compiler/src/main/kotlin/com/android/databinding/main.kt204
-rw-r--r--compiler/src/main/kotlin/com/android/databinding/util/Log.kt4
-rw-r--r--compiler/src/main/kotlin/com/android/databinding/util/XmlEditor.kt117
-rw-r--r--gradle/wrapper/gradle-wrapper.jarbin51017 -> 49896 bytes
-rw-r--r--gradle/wrapper/gradle-wrapper.properties4
-rw-r--r--gradlePlugin/src/main/kotlin/plugin.kt14
-rwxr-xr-xgradlew164
-rw-r--r--grammerBuilder/build.gradle1
-rw-r--r--grammerBuilder/src/main/java/com/android/databinder/parser/Main.java1
-rw-r--r--library/build.gradle1
-rw-r--r--samples/BindingDemo/app/src/main/res/layout/list_item.xml10
-rw-r--r--samples/BindingDemo/app/src/main/res/layout/main_activity.xml46
-rw-r--r--settings.gradle4
-rw-r--r--xmlGrammer/XMLLexer.g493
-rw-r--r--xmlGrammer/XMLParser.g454
-rw-r--r--xmlGrammer/build.gradle42
-rw-r--r--xmlGrammer/src/main/java/com/android/databinding/XMLLexer.java138
-rw-r--r--xmlGrammer/src/main/java/com/android/databinding/XMLLexer.tokens23
-rw-r--r--xmlGrammer/src/main/java/com/android/databinding/XMLParser.java660
-rw-r--r--xmlGrammer/src/main/java/com/android/databinding/XMLParser.tokens23
-rw-r--r--xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseListener.java144
-rw-r--r--xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseVisitor.java79
-rw-r--r--xmlGrammer/src/main/java/com/android/databinding/XMLParserListener.java99
-rw-r--r--xmlGrammer/src/main/java/com/android/databinding/XMLParserVisitor.java70
-rw-r--r--xmlGrammer/src/main/kotlin/xmlEditorTest.kt131
27 files changed, 2055 insertions, 91 deletions
diff --git a/compiler/build.gradle b/compiler/build.gradle
index bc6046e7..07898eda 100644
--- a/compiler/build.gradle
+++ b/compiler/build.gradle
@@ -33,6 +33,7 @@ buildscript {
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
compile project(":grammerBuilder")
+ compile project(":xmlGrammer")
}
uploadArchives {
repositories {
diff --git a/compiler/src/main/kotlin/com/android/databinding/ext/node_ext.kt b/compiler/src/main/kotlin/com/android/databinding/ext/node_ext.kt
index 97f29a3e..4ddc0794 100644
--- a/compiler/src/main/kotlin/com/android/databinding/ext/node_ext.kt
+++ b/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 @@ public fun Node.getAndroidIdPath(includeRoot : Boolean) : List<String> {
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/compiler/src/main/kotlin/com/android/databinding/main.kt b/compiler/src/main/kotlin/com/android/databinding/main.kt
index 70d69d6e..686bca36 100644
--- a/compiler/src/main/kotlin/com/android/databinding/main.kt
+++ b/compiler/src/main/kotlin/com/android/databinding/main.kt
@@ -48,7 +48,15 @@ import com.android.databinding.vo.LayoutExprBinding
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 @@ public class KLayoutParser(val appPkg : String, val resourceFolders : kotlin.Ite
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 @@ public class KLayoutParser(val appPkg : String, val resourceFolders : kotlin.Ite
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 @@ public class KLayoutParser(val appPkg : String, val resourceFolders : kotlin.Ite
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 @@ public class KLayoutParser(val appPkg : String, val resourceFolders : kotlin.Ite
//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 class KLayoutParser(val appPkg : String, val resourceFolders : kotlin.Ite
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 @@ public class KLayoutParser(val appPkg : String, val resourceFolders : kotlin.Ite
private fun toLayoutId(name:String) : String =
name.substring(0, name.indexOf("."))
+ 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 @@ public class KLayoutParser(val appPkg : String, val resourceFolders : kotlin.Ite
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/compiler/src/main/kotlin/com/android/databinding/util/Log.kt b/compiler/src/main/kotlin/com/android/databinding/util/Log.kt
index e8fe446d..28c1807a 100644
--- a/compiler/src/main/kotlin/com/android/databinding/util/Log.kt
+++ b/compiler/src/main/kotlin/com/android/databinding/util/Log.kt
@@ -20,4 +20,8 @@ object Log {
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/compiler/src/main/kotlin/com/android/databinding/util/XmlEditor.kt b/compiler/src/main/kotlin/com/android/databinding/util/XmlEditor.kt
new file mode 100644
index 00000000..815108d6
--- /dev/null
+++ b/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/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 3d0dee6e..8c0fb64a 100644
--- a/gradle/wrapper/gradle-wrapper.jar
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 37c1f85b..ddbd6130 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/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/gradlePlugin/src/main/kotlin/plugin.kt b/gradlePlugin/src/main/kotlin/plugin.kt
index c5a0cf89..535659d1 100644
--- a/gradlePlugin/src/main/kotlin/plugin.kt
+++ b/gradlePlugin/src/main/kotlin/plugin.kt
@@ -74,14 +74,13 @@ class DataBinderPlugin : Plugin<Project> {
// 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 @@ class DataBinderPlugin : Plugin<Project> {
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 @@ class DataBinderPlugin : Plugin<Project> {
}
fun generateAttr(o: Any?) {
+ parser.processIfNecessary()
log("generate attr ${o}")
parser.writeAttrFile()
}
@@ -227,6 +228,7 @@ class DataBinderPlugin : Plugin<Project> {
}
fun generateBrFile(o: Any?) {
+ parser.processIfNecessary()
log("generating BR ${o}")
parser.writeBrFile()
parser.writeViewBinderInterfaces()
diff --git a/gradlew b/gradlew
new file mode 100755
index 00000000..91a7e269
--- /dev/null
+++ b/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/grammerBuilder/build.gradle b/grammerBuilder/build.gradle
index 5b55bf88..122e3d6b 100644
--- a/grammerBuilder/build.gradle
+++ b/grammerBuilder/build.gradle
@@ -26,7 +26,6 @@ run {
}
dependencies {
- testCompile 'junit:junit:4.11'
compile 'com.tunnelvisionlabs:antlr4:4.4'
}
diff --git a/grammerBuilder/src/main/java/com/android/databinder/parser/Main.java b/grammerBuilder/src/main/java/com/android/databinder/parser/Main.java
index a8406de0..ba5c3958 100644
--- a/grammerBuilder/src/main/java/com/android/databinder/parser/Main.java
+++ b/grammerBuilder/src/main/java/com/android/databinder/parser/Main.java
@@ -32,6 +32,7 @@ public class Main {
// DataBinderParser parser = new DataBinderParser(tokenStream);
// ParseTreeWalker walker = new ParseTreeWalker();
// System.out.println(parser.expr().toStringTree(parser));
+ float[] aa = new float[2];
}
}
diff --git a/library/build.gradle b/library/build.gradle
index e97c54b0..dd49c3f8 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -1,4 +1,3 @@
-
/*
* Copyright (C) 2014 The Android Open Source Project
*
diff --git a/samples/BindingDemo/app/src/main/res/layout/list_item.xml b/samples/BindingDemo/app/src/main/res/layout/list_item.xml
index d1db3ac9..54d8f1be 100644
--- a/samples/BindingDemo/app/src/main/res/layout/list_item.xml
+++ b/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/samples/BindingDemo/app/src/main/res/layout/main_activity.xml b/samples/BindingDemo/app/src/main/res/layout/main_activity.xml
index 8cde9e2a..a2b52d5b 100644
--- a/samples/BindingDemo/app/src/main/res/layout/main_activity.xml
+++ b/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/settings.gradle b/settings.gradle
index c069a579..5dea8c3c 100644
--- a/settings.gradle
+++ b/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/xmlGrammer/XMLLexer.g4 b/xmlGrammer/XMLLexer.g4
new file mode 100644
index 00000000..ea7a23c4
--- /dev/null
+++ b/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/xmlGrammer/XMLParser.g4 b/xmlGrammer/XMLParser.g4
new file mode 100644
index 00000000..1b03e2d5
--- /dev/null
+++ b/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/xmlGrammer/build.gradle b/xmlGrammer/build.gradle
new file mode 100644
index 00000000..2489f0e5
--- /dev/null
+++ b/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/xmlGrammer/src/main/java/com/android/databinding/XMLLexer.java b/xmlGrammer/src/main/java/com/android/databinding/XMLLexer.java
new file mode 100644
index 00000000..5d856411
--- /dev/null
+++ b/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/xmlGrammer/src/main/java/com/android/databinding/XMLLexer.tokens b/xmlGrammer/src/main/java/com/android/databinding/XMLLexer.tokens
new file mode 100644
index 00000000..cd122a48
--- /dev/null
+++ b/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/xmlGrammer/src/main/java/com/android/databinding/XMLParser.java b/xmlGrammer/src/main/java/com/android/databinding/XMLParser.java
new file mode 100644
index 00000000..a3244942
--- /dev/null
+++ b/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/xmlGrammer/src/main/java/com/android/databinding/XMLParser.tokens b/xmlGrammer/src/main/java/com/android/databinding/XMLParser.tokens
new file mode 100644
index 00000000..b1423a12
--- /dev/null
+++ b/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/xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseListener.java b/xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseListener.java
new file mode 100644
index 00000000..9c438423
--- /dev/null
+++ b/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/xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseVisitor.java b/xmlGrammer/src/main/java/com/android/databinding/XMLParserBaseVisitor.java
new file mode 100644
index 00000000..91d18e76
--- /dev/null
+++ b/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/xmlGrammer/src/main/java/com/android/databinding/XMLParserListener.java b/xmlGrammer/src/main/java/com/android/databinding/XMLParserListener.java
new file mode 100644
index 00000000..b5499a6b
--- /dev/null
+++ b/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/xmlGrammer/src/main/java/com/android/databinding/XMLParserVisitor.java b/xmlGrammer/src/main/java/com/android/databinding/XMLParserVisitor.java
new file mode 100644
index 00000000..58a65f40
--- /dev/null
+++ b/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/xmlGrammer/src/main/kotlin/xmlEditorTest.kt b/xmlGrammer/src/main/kotlin/xmlEditorTest.kt
new file mode 100644
index 00000000..2f9d0da3
--- /dev/null
+++ b/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) {
+}