diff options
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 Binary files differindex 3d0dee6e..8c0fb64a 100644 --- a/gradle/wrapper/gradle-wrapper.jar +++ b/gradle/wrapper/gradle-wrapper.jar 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() + ". " + user.lastName" + android:text="{user.name.substring(0,1).toUpperCase() + ". " + 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 + " Robots "" /> + android:text="{activity.robotAdapter.itemCount + " Robots "}" /> <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) { +} |