diff --git a/rewrite-xml/src/main/antlr/XMLParser.g4 b/rewrite-xml/src/main/antlr/XMLParser.g4 index 2477fc33025..69fb3fa50eb 100755 --- a/rewrite-xml/src/main/antlr/XMLParser.g4 +++ b/rewrite-xml/src/main/antlr/XMLParser.g4 @@ -81,8 +81,16 @@ content : (element | reference | processinginstruction | CDATA | COMMENT | jspscriptlet | jspexpression | jspdeclaration | jspcomment | chardata) ; +// Strict XML and HTML-like sources get separate alternatives rather than one shared, left-factored shape. +// The shape of this rule determines the resynchronization sets ANTLR's error recovery uses, so folding the +// two together would let HTML void element support change how malformed *XML* recovers -- e.g. an attribute +// whose value contains an unescaped quote could recover with a synthesized '=' that the printer then emits +// into the source. Keeping the strict-XML alternatives exactly as they were before void element support +// existed is what makes "HTML support does not affect XML parsing" true of recovery and not just of matching. element - : OPEN name=Name attribute* + : {!isHtmlMode()}? OPEN name=Name attribute* CLOSE content* OPEN '/' Name CLOSE + | {!isHtmlMode()}? OPEN name=Name attribute* '/>' + | {isHtmlMode()}? OPEN name=Name attribute* ( '/>' | CLOSE ( {isVoidElement($name.text)}? voidClose // HTML void element, e.g.
with no closing tag diff --git a/rewrite-xml/src/main/java/org/openrewrite/xml/internal/XmlParserVisitor.java b/rewrite-xml/src/main/java/org/openrewrite/xml/internal/XmlParserVisitor.java index c8d8fe323a7..38959066d2a 100755 --- a/rewrite-xml/src/main/java/org/openrewrite/xml/internal/XmlParserVisitor.java +++ b/rewrite-xml/src/main/java/org/openrewrite/xml/internal/XmlParserVisitor.java @@ -328,6 +328,9 @@ public Xml visitJspcomment(XMLParser.JspcommentContext ctx) { @Override public Xml.Tag visitElement(XMLParser.ElementContext ctx) { + if (ctx != null && ctx.Name(0) == null) { + throw malformed(ctx.getStart(), "an element is missing its name"); + } return convert(ctx, (c, prefix) -> { String name = convert(ctx.Name(0), (n, p) -> n.getText()); @@ -389,6 +392,7 @@ public Xml.Tag visitElement(XMLParser.ElementContext ctx) { @Override public Xml.Attribute visitAttribute(XMLParser.AttributeContext ctx) { + requireWellFormed(ctx); return convert(ctx, (c, prefix) -> { Xml.Ident key = convert(c.Name(), (t, p) -> new Xml.Ident(randomId(), p, Markers.EMPTY, t.getText())); @@ -407,6 +411,33 @@ public Xml.Attribute visitAttribute(XMLParser.AttributeContext ctx) { }); } + /** + * An attribute is only reachable here with a part missing, or with a part ANTLR invented, when error recovery + * built it out of tokens that were never an attribute in the source. Reading such a context yields a tree that no + * longer represents the source: a synthesized {@code =} is indistinguishable from a real one once built, and the + * printer then emits it back into the attribute value. + */ + private void requireWellFormed(XMLParser.@Nullable AttributeContext ctx) { + if (ctx != null && (ctx.Name() == null || ctx.STRING() == null || isSynthesized(ctx.EQUALS()))) { + throw malformed(ctx.getStart(), "an attribute value contains an unescaped '\"' or '<'"); + } + } + + private static boolean isSynthesized(@Nullable TerminalNode node) { + return node == null || node.getSymbol().getTokenIndex() < 0; + } + + /** + * Rejects input that is not well-formed XML, so the caller falls back to a + * {@link org.openrewrite.tree.ParseError} that preserves the original text rather than building an LST out of + * whatever ANTLR error recovery happened to leave behind. + */ + private IllegalStateException malformed(Token start, String detail) { + return new IllegalStateException(String.format( + "%s is not well-formed XML: %s at line %d:%d.", + path, detail, start.getLine(), start.getCharPositionInLine())); + } + @Override public Xml.DocTypeDecl visitDoctypedecl(XMLParser.DoctypedeclContext ctx) { return convert(ctx, (c, prefix) -> { diff --git a/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParser.interp b/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParser.interp index 3ed6ca925b9..06db096714e 100755 --- a/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParser.interp +++ b/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParser.interp @@ -113,4 +113,4 @@ chardata atn: -[4, 1, 42, 212, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 1, 0, 3, 0, 44, 8, 0, 1, 0, 1, 0, 3, 0, 48, 8, 0, 1, 1, 3, 1, 51, 8, 1, 1, 1, 5, 1, 54, 8, 1, 10, 1, 12, 1, 57, 9, 1, 1, 1, 5, 1, 60, 8, 1, 10, 1, 12, 1, 63, 9, 1, 1, 2, 1, 2, 5, 2, 67, 8, 2, 10, 2, 12, 2, 70, 9, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 79, 8, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 86, 8, 4, 10, 4, 12, 4, 89, 9, 4, 1, 4, 1, 4, 1, 4, 1, 4, 3, 4, 95, 8, 4, 1, 4, 1, 4, 1, 5, 1, 5, 5, 5, 101, 8, 5, 10, 5, 12, 5, 104, 9, 5, 1, 6, 1, 6, 5, 6, 108, 8, 6, 10, 6, 12, 6, 111, 9, 6, 1, 6, 5, 6, 114, 8, 6, 10, 6, 12, 6, 117, 9, 6, 1, 6, 5, 6, 120, 8, 6, 10, 6, 12, 6, 123, 9, 6, 1, 6, 1, 6, 1, 6, 3, 6, 128, 8, 6, 1, 7, 1, 7, 1, 8, 3, 8, 133, 8, 8, 1, 9, 1, 9, 5, 9, 137, 8, 9, 10, 9, 12, 9, 140, 9, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 3, 10, 154, 8, 10, 1, 11, 1, 11, 1, 11, 5, 11, 159, 8, 11, 10, 11, 12, 11, 162, 9, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 169, 8, 11, 10, 11, 12, 11, 172, 9, 11, 1, 11, 1, 11, 1, 11, 1, 11, 3, 11, 178, 8, 11, 3, 11, 180, 8, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 188, 8, 13, 10, 13, 12, 13, 191, 9, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 0, 0, 21, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 0, 3, 1, 0, 28, 29, 1, 0, 5, 6, 3, 0, 7, 7, 9, 9, 18, 18, 225, 0, 43, 1, 0, 0, 0, 2, 50, 1, 0, 0, 0, 4, 64, 1, 0, 0, 0, 6, 78, 1, 0, 0, 0, 8, 80, 1, 0, 0, 0, 10, 102, 1, 0, 0, 0, 12, 127, 1, 0, 0, 0, 14, 129, 1, 0, 0, 0, 16, 132, 1, 0, 0, 0, 18, 134, 1, 0, 0, 0, 20, 153, 1, 0, 0, 0, 22, 155, 1, 0, 0, 0, 24, 181, 1, 0, 0, 0, 26, 183, 1, 0, 0, 0, 28, 195, 1, 0, 0, 0, 30, 197, 1, 0, 0, 0, 32, 199, 1, 0, 0, 0, 34, 201, 1, 0, 0, 0, 36, 203, 1, 0, 0, 0, 38, 205, 1, 0, 0, 0, 40, 209, 1, 0, 0, 0, 42, 44, 5, 8, 0, 0, 43, 42, 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 45, 1, 0, 0, 0, 45, 47, 3, 2, 1, 0, 46, 48, 3, 22, 11, 0, 47, 46, 1, 0, 0, 0, 47, 48, 1, 0, 0, 0, 48, 1, 1, 0, 0, 0, 49, 51, 3, 4, 2, 0, 50, 49, 1, 0, 0, 0, 50, 51, 1, 0, 0, 0, 51, 55, 1, 0, 0, 0, 52, 54, 3, 6, 3, 0, 53, 52, 1, 0, 0, 0, 54, 57, 1, 0, 0, 0, 55, 53, 1, 0, 0, 0, 55, 56, 1, 0, 0, 0, 56, 61, 1, 0, 0, 0, 57, 55, 1, 0, 0, 0, 58, 60, 3, 26, 13, 0, 59, 58, 1, 0, 0, 0, 60, 63, 1, 0, 0, 0, 61, 59, 1, 0, 0, 0, 61, 62, 1, 0, 0, 0, 62, 3, 1, 0, 0, 0, 63, 61, 1, 0, 0, 0, 64, 68, 5, 10, 0, 0, 65, 67, 3, 38, 19, 0, 66, 65, 1, 0, 0, 0, 67, 70, 1, 0, 0, 0, 68, 66, 1, 0, 0, 0, 68, 69, 1, 0, 0, 0, 69, 71, 1, 0, 0, 0, 70, 68, 1, 0, 0, 0, 71, 72, 5, 34, 0, 0, 72, 5, 1, 0, 0, 0, 73, 79, 5, 2, 0, 0, 74, 79, 3, 8, 4, 0, 75, 79, 3, 18, 9, 0, 76, 79, 3, 32, 16, 0, 77, 79, 3, 34, 17, 0, 78, 73, 1, 0, 0, 0, 78, 74, 1, 0, 0, 0, 78, 75, 1, 0, 0, 0, 78, 76, 1, 0, 0, 0, 78, 77, 1, 0, 0, 0, 79, 7, 1, 0, 0, 0, 80, 81, 5, 13, 0, 0, 81, 82, 5, 22, 0, 0, 82, 83, 5, 42, 0, 0, 83, 87, 3, 16, 8, 0, 84, 86, 5, 41, 0, 0, 85, 84, 1, 0, 0, 0, 86, 89, 1, 0, 0, 0, 87, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 94, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 90, 91, 5, 20, 0, 0, 91, 92, 3, 10, 5, 0, 92, 93, 5, 23, 0, 0, 93, 95, 1, 0, 0, 0, 94, 90, 1, 0, 0, 0, 94, 95, 1, 0, 0, 0, 95, 96, 1, 0, 0, 0, 96, 97, 5, 19, 0, 0, 97, 9, 1, 0, 0, 0, 98, 101, 3, 12, 6, 0, 99, 101, 3, 14, 7, 0, 100, 98, 1, 0, 0, 0, 100, 99, 1, 0, 0, 0, 101, 104, 1, 0, 0, 0, 102, 100, 1, 0, 0, 0, 102, 103, 1, 0, 0, 0, 103, 11, 1, 0, 0, 0, 104, 102, 1, 0, 0, 0, 105, 109, 5, 24, 0, 0, 106, 108, 7, 0, 0, 0, 107, 106, 1, 0, 0, 0, 108, 111, 1, 0, 0, 0, 109, 107, 1, 0, 0, 0, 109, 110, 1, 0, 0, 0, 110, 115, 1, 0, 0, 0, 111, 109, 1, 0, 0, 0, 112, 114, 5, 30, 0, 0, 113, 112, 1, 0, 0, 0, 114, 117, 1, 0, 0, 0, 115, 113, 1, 0, 0, 0, 115, 116, 1, 0, 0, 0, 116, 121, 1, 0, 0, 0, 117, 115, 1, 0, 0, 0, 118, 120, 7, 0, 0, 0, 119, 118, 1, 0, 0, 0, 120, 123, 1, 0, 0, 0, 121, 119, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 124, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 124, 128, 5, 26, 0, 0, 125, 128, 3, 18, 9, 0, 126, 128, 5, 2, 0, 0, 127, 105, 1, 0, 0, 0, 127, 125, 1, 0, 0, 0, 127, 126, 1, 0, 0, 0, 128, 13, 1, 0, 0, 0, 129, 130, 5, 4, 0, 0, 130, 15, 1, 0, 0, 0, 131, 133, 5, 42, 0, 0, 132, 131, 1, 0, 0, 0, 132, 133, 1, 0, 0, 0, 133, 17, 1, 0, 0, 0, 134, 138, 5, 12, 0, 0, 135, 137, 5, 32, 0, 0, 136, 135, 1, 0, 0, 0, 137, 140, 1, 0, 0, 0, 138, 136, 1, 0, 0, 0, 138, 139, 1, 0, 0, 0, 139, 141, 1, 0, 0, 0, 140, 138, 1, 0, 0, 0, 141, 142, 5, 34, 0, 0, 142, 19, 1, 0, 0, 0, 143, 154, 3, 22, 11, 0, 144, 154, 3, 36, 18, 0, 145, 154, 3, 18, 9, 0, 146, 154, 5, 3, 0, 0, 147, 154, 5, 2, 0, 0, 148, 154, 3, 28, 14, 0, 149, 154, 3, 30, 15, 0, 150, 154, 3, 32, 16, 0, 151, 154, 3, 34, 17, 0, 152, 154, 3, 40, 20, 0, 153, 143, 1, 0, 0, 0, 153, 144, 1, 0, 0, 0, 153, 145, 1, 0, 0, 0, 153, 146, 1, 0, 0, 0, 153, 147, 1, 0, 0, 0, 153, 148, 1, 0, 0, 0, 153, 149, 1, 0, 0, 0, 153, 150, 1, 0, 0, 0, 153, 151, 1, 0, 0, 0, 153, 152, 1, 0, 0, 0, 154, 21, 1, 0, 0, 0, 155, 156, 5, 11, 0, 0, 156, 160, 5, 42, 0, 0, 157, 159, 3, 38, 19, 0, 158, 157, 1, 0, 0, 0, 159, 162, 1, 0, 0, 0, 160, 158, 1, 0, 0, 0, 160, 161, 1, 0, 0, 0, 161, 179, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 163, 180, 5, 35, 0, 0, 164, 177, 5, 33, 0, 0, 165, 166, 4, 11, 0, 1, 166, 178, 3, 24, 12, 0, 167, 169, 3, 20, 10, 0, 168, 167, 1, 0, 0, 0, 169, 172, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 170, 171, 1, 0, 0, 0, 171, 173, 1, 0, 0, 0, 172, 170, 1, 0, 0, 0, 173, 174, 5, 11, 0, 0, 174, 175, 5, 39, 0, 0, 175, 176, 5, 42, 0, 0, 176, 178, 5, 33, 0, 0, 177, 165, 1, 0, 0, 0, 177, 170, 1, 0, 0, 0, 178, 180, 1, 0, 0, 0, 179, 163, 1, 0, 0, 0, 179, 164, 1, 0, 0, 0, 180, 23, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 25, 1, 0, 0, 0, 183, 184, 5, 11, 0, 0, 184, 185, 5, 37, 0, 0, 185, 189, 5, 42, 0, 0, 186, 188, 3, 38, 19, 0, 187, 186, 1, 0, 0, 0, 188, 191, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 192, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 192, 193, 5, 38, 0, 0, 193, 194, 5, 33, 0, 0, 194, 27, 1, 0, 0, 0, 195, 196, 5, 17, 0, 0, 196, 29, 1, 0, 0, 0, 197, 198, 5, 16, 0, 0, 198, 31, 1, 0, 0, 0, 199, 200, 5, 15, 0, 0, 200, 33, 1, 0, 0, 0, 201, 202, 5, 14, 0, 0, 202, 35, 1, 0, 0, 0, 203, 204, 7, 1, 0, 0, 204, 37, 1, 0, 0, 0, 205, 206, 5, 42, 0, 0, 206, 207, 5, 40, 0, 0, 207, 208, 5, 41, 0, 0, 208, 39, 1, 0, 0, 0, 209, 210, 7, 2, 0, 0, 210, 41, 1, 0, 0, 0, 23, 43, 47, 50, 55, 61, 68, 78, 87, 94, 100, 102, 109, 115, 121, 127, 132, 138, 153, 160, 170, 177, 179, 189] \ No newline at end of file +[4, 1, 42, 245, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 1, 0, 3, 0, 44, 8, 0, 1, 0, 1, 0, 3, 0, 48, 8, 0, 1, 1, 3, 1, 51, 8, 1, 1, 1, 5, 1, 54, 8, 1, 10, 1, 12, 1, 57, 9, 1, 1, 1, 5, 1, 60, 8, 1, 10, 1, 12, 1, 63, 9, 1, 1, 2, 1, 2, 5, 2, 67, 8, 2, 10, 2, 12, 2, 70, 9, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 79, 8, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 86, 8, 4, 10, 4, 12, 4, 89, 9, 4, 1, 4, 1, 4, 1, 4, 1, 4, 3, 4, 95, 8, 4, 1, 4, 1, 4, 1, 5, 1, 5, 5, 5, 101, 8, 5, 10, 5, 12, 5, 104, 9, 5, 1, 6, 1, 6, 5, 6, 108, 8, 6, 10, 6, 12, 6, 111, 9, 6, 1, 6, 5, 6, 114, 8, 6, 10, 6, 12, 6, 117, 9, 6, 1, 6, 5, 6, 120, 8, 6, 10, 6, 12, 6, 123, 9, 6, 1, 6, 1, 6, 1, 6, 3, 6, 128, 8, 6, 1, 7, 1, 7, 1, 8, 3, 8, 133, 8, 8, 1, 9, 1, 9, 5, 9, 137, 8, 9, 10, 9, 12, 9, 140, 9, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 3, 10, 154, 8, 10, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 160, 8, 11, 10, 11, 12, 11, 163, 9, 11, 1, 11, 1, 11, 5, 11, 167, 8, 11, 10, 11, 12, 11, 170, 9, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 180, 8, 11, 10, 11, 12, 11, 183, 9, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 190, 8, 11, 10, 11, 12, 11, 193, 9, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 200, 8, 11, 10, 11, 12, 11, 203, 9, 11, 1, 11, 1, 11, 1, 11, 1, 11, 3, 11, 209, 8, 11, 3, 11, 211, 8, 11, 3, 11, 213, 8, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 221, 8, 13, 10, 13, 12, 13, 224, 9, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 0, 0, 21, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 0, 3, 1, 0, 28, 29, 1, 0, 5, 6, 3, 0, 7, 7, 9, 9, 18, 18, 263, 0, 43, 1, 0, 0, 0, 2, 50, 1, 0, 0, 0, 4, 64, 1, 0, 0, 0, 6, 78, 1, 0, 0, 0, 8, 80, 1, 0, 0, 0, 10, 102, 1, 0, 0, 0, 12, 127, 1, 0, 0, 0, 14, 129, 1, 0, 0, 0, 16, 132, 1, 0, 0, 0, 18, 134, 1, 0, 0, 0, 20, 153, 1, 0, 0, 0, 22, 212, 1, 0, 0, 0, 24, 214, 1, 0, 0, 0, 26, 216, 1, 0, 0, 0, 28, 228, 1, 0, 0, 0, 30, 230, 1, 0, 0, 0, 32, 232, 1, 0, 0, 0, 34, 234, 1, 0, 0, 0, 36, 236, 1, 0, 0, 0, 38, 238, 1, 0, 0, 0, 40, 242, 1, 0, 0, 0, 42, 44, 5, 8, 0, 0, 43, 42, 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 45, 1, 0, 0, 0, 45, 47, 3, 2, 1, 0, 46, 48, 3, 22, 11, 0, 47, 46, 1, 0, 0, 0, 47, 48, 1, 0, 0, 0, 48, 1, 1, 0, 0, 0, 49, 51, 3, 4, 2, 0, 50, 49, 1, 0, 0, 0, 50, 51, 1, 0, 0, 0, 51, 55, 1, 0, 0, 0, 52, 54, 3, 6, 3, 0, 53, 52, 1, 0, 0, 0, 54, 57, 1, 0, 0, 0, 55, 53, 1, 0, 0, 0, 55, 56, 1, 0, 0, 0, 56, 61, 1, 0, 0, 0, 57, 55, 1, 0, 0, 0, 58, 60, 3, 26, 13, 0, 59, 58, 1, 0, 0, 0, 60, 63, 1, 0, 0, 0, 61, 59, 1, 0, 0, 0, 61, 62, 1, 0, 0, 0, 62, 3, 1, 0, 0, 0, 63, 61, 1, 0, 0, 0, 64, 68, 5, 10, 0, 0, 65, 67, 3, 38, 19, 0, 66, 65, 1, 0, 0, 0, 67, 70, 1, 0, 0, 0, 68, 66, 1, 0, 0, 0, 68, 69, 1, 0, 0, 0, 69, 71, 1, 0, 0, 0, 70, 68, 1, 0, 0, 0, 71, 72, 5, 34, 0, 0, 72, 5, 1, 0, 0, 0, 73, 79, 5, 2, 0, 0, 74, 79, 3, 8, 4, 0, 75, 79, 3, 18, 9, 0, 76, 79, 3, 32, 16, 0, 77, 79, 3, 34, 17, 0, 78, 73, 1, 0, 0, 0, 78, 74, 1, 0, 0, 0, 78, 75, 1, 0, 0, 0, 78, 76, 1, 0, 0, 0, 78, 77, 1, 0, 0, 0, 79, 7, 1, 0, 0, 0, 80, 81, 5, 13, 0, 0, 81, 82, 5, 22, 0, 0, 82, 83, 5, 42, 0, 0, 83, 87, 3, 16, 8, 0, 84, 86, 5, 41, 0, 0, 85, 84, 1, 0, 0, 0, 86, 89, 1, 0, 0, 0, 87, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 94, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 90, 91, 5, 20, 0, 0, 91, 92, 3, 10, 5, 0, 92, 93, 5, 23, 0, 0, 93, 95, 1, 0, 0, 0, 94, 90, 1, 0, 0, 0, 94, 95, 1, 0, 0, 0, 95, 96, 1, 0, 0, 0, 96, 97, 5, 19, 0, 0, 97, 9, 1, 0, 0, 0, 98, 101, 3, 12, 6, 0, 99, 101, 3, 14, 7, 0, 100, 98, 1, 0, 0, 0, 100, 99, 1, 0, 0, 0, 101, 104, 1, 0, 0, 0, 102, 100, 1, 0, 0, 0, 102, 103, 1, 0, 0, 0, 103, 11, 1, 0, 0, 0, 104, 102, 1, 0, 0, 0, 105, 109, 5, 24, 0, 0, 106, 108, 7, 0, 0, 0, 107, 106, 1, 0, 0, 0, 108, 111, 1, 0, 0, 0, 109, 107, 1, 0, 0, 0, 109, 110, 1, 0, 0, 0, 110, 115, 1, 0, 0, 0, 111, 109, 1, 0, 0, 0, 112, 114, 5, 30, 0, 0, 113, 112, 1, 0, 0, 0, 114, 117, 1, 0, 0, 0, 115, 113, 1, 0, 0, 0, 115, 116, 1, 0, 0, 0, 116, 121, 1, 0, 0, 0, 117, 115, 1, 0, 0, 0, 118, 120, 7, 0, 0, 0, 119, 118, 1, 0, 0, 0, 120, 123, 1, 0, 0, 0, 121, 119, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 124, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 124, 128, 5, 26, 0, 0, 125, 128, 3, 18, 9, 0, 126, 128, 5, 2, 0, 0, 127, 105, 1, 0, 0, 0, 127, 125, 1, 0, 0, 0, 127, 126, 1, 0, 0, 0, 128, 13, 1, 0, 0, 0, 129, 130, 5, 4, 0, 0, 130, 15, 1, 0, 0, 0, 131, 133, 5, 42, 0, 0, 132, 131, 1, 0, 0, 0, 132, 133, 1, 0, 0, 0, 133, 17, 1, 0, 0, 0, 134, 138, 5, 12, 0, 0, 135, 137, 5, 32, 0, 0, 136, 135, 1, 0, 0, 0, 137, 140, 1, 0, 0, 0, 138, 136, 1, 0, 0, 0, 138, 139, 1, 0, 0, 0, 139, 141, 1, 0, 0, 0, 140, 138, 1, 0, 0, 0, 141, 142, 5, 34, 0, 0, 142, 19, 1, 0, 0, 0, 143, 154, 3, 22, 11, 0, 144, 154, 3, 36, 18, 0, 145, 154, 3, 18, 9, 0, 146, 154, 5, 3, 0, 0, 147, 154, 5, 2, 0, 0, 148, 154, 3, 28, 14, 0, 149, 154, 3, 30, 15, 0, 150, 154, 3, 32, 16, 0, 151, 154, 3, 34, 17, 0, 152, 154, 3, 40, 20, 0, 153, 143, 1, 0, 0, 0, 153, 144, 1, 0, 0, 0, 153, 145, 1, 0, 0, 0, 153, 146, 1, 0, 0, 0, 153, 147, 1, 0, 0, 0, 153, 148, 1, 0, 0, 0, 153, 149, 1, 0, 0, 0, 153, 150, 1, 0, 0, 0, 153, 151, 1, 0, 0, 0, 153, 152, 1, 0, 0, 0, 154, 21, 1, 0, 0, 0, 155, 156, 4, 11, 0, 0, 156, 157, 5, 11, 0, 0, 157, 161, 5, 42, 0, 0, 158, 160, 3, 38, 19, 0, 159, 158, 1, 0, 0, 0, 160, 163, 1, 0, 0, 0, 161, 159, 1, 0, 0, 0, 161, 162, 1, 0, 0, 0, 162, 164, 1, 0, 0, 0, 163, 161, 1, 0, 0, 0, 164, 168, 5, 33, 0, 0, 165, 167, 3, 20, 10, 0, 166, 165, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 172, 5, 11, 0, 0, 172, 173, 5, 39, 0, 0, 173, 174, 5, 42, 0, 0, 174, 213, 5, 33, 0, 0, 175, 176, 4, 11, 1, 0, 176, 177, 5, 11, 0, 0, 177, 181, 5, 42, 0, 0, 178, 180, 3, 38, 19, 0, 179, 178, 1, 0, 0, 0, 180, 183, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 184, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 184, 213, 5, 35, 0, 0, 185, 186, 4, 11, 2, 0, 186, 187, 5, 11, 0, 0, 187, 191, 5, 42, 0, 0, 188, 190, 3, 38, 19, 0, 189, 188, 1, 0, 0, 0, 190, 193, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 191, 192, 1, 0, 0, 0, 192, 210, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 194, 211, 5, 35, 0, 0, 195, 208, 5, 33, 0, 0, 196, 197, 4, 11, 3, 1, 197, 209, 3, 24, 12, 0, 198, 200, 3, 20, 10, 0, 199, 198, 1, 0, 0, 0, 200, 203, 1, 0, 0, 0, 201, 199, 1, 0, 0, 0, 201, 202, 1, 0, 0, 0, 202, 204, 1, 0, 0, 0, 203, 201, 1, 0, 0, 0, 204, 205, 5, 11, 0, 0, 205, 206, 5, 39, 0, 0, 206, 207, 5, 42, 0, 0, 207, 209, 5, 33, 0, 0, 208, 196, 1, 0, 0, 0, 208, 201, 1, 0, 0, 0, 209, 211, 1, 0, 0, 0, 210, 194, 1, 0, 0, 0, 210, 195, 1, 0, 0, 0, 211, 213, 1, 0, 0, 0, 212, 155, 1, 0, 0, 0, 212, 175, 1, 0, 0, 0, 212, 185, 1, 0, 0, 0, 213, 23, 1, 0, 0, 0, 214, 215, 1, 0, 0, 0, 215, 25, 1, 0, 0, 0, 216, 217, 5, 11, 0, 0, 217, 218, 5, 37, 0, 0, 218, 222, 5, 42, 0, 0, 219, 221, 3, 38, 19, 0, 220, 219, 1, 0, 0, 0, 221, 224, 1, 0, 0, 0, 222, 220, 1, 0, 0, 0, 222, 223, 1, 0, 0, 0, 223, 225, 1, 0, 0, 0, 224, 222, 1, 0, 0, 0, 225, 226, 5, 38, 0, 0, 226, 227, 5, 33, 0, 0, 227, 27, 1, 0, 0, 0, 228, 229, 5, 17, 0, 0, 229, 29, 1, 0, 0, 0, 230, 231, 5, 16, 0, 0, 231, 31, 1, 0, 0, 0, 232, 233, 5, 15, 0, 0, 233, 33, 1, 0, 0, 0, 234, 235, 5, 14, 0, 0, 235, 35, 1, 0, 0, 0, 236, 237, 7, 1, 0, 0, 237, 37, 1, 0, 0, 0, 238, 239, 5, 42, 0, 0, 239, 240, 5, 40, 0, 0, 240, 241, 5, 41, 0, 0, 241, 39, 1, 0, 0, 0, 242, 243, 7, 2, 0, 0, 243, 41, 1, 0, 0, 0, 27, 43, 47, 50, 55, 61, 68, 78, 87, 94, 100, 102, 109, 115, 121, 127, 132, 138, 153, 161, 168, 181, 191, 201, 208, 210, 212, 222] \ No newline at end of file diff --git a/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParser.java b/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParser.java index 24caab5856a..d3b1bc99b38 100644 --- a/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParser.java +++ b/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParser.java @@ -160,32 +160,31 @@ public T accept(ParseTreeVisitor visitor) { public final DocumentContext document() throws RecognitionException { DocumentContext _localctx = new DocumentContext(_ctx, getState()); enterRule(_localctx, 0, RULE_document); - int _la; try { enterOuterAlt(_localctx, 1); { setState(43); _errHandler.sync(this); - _la = _input.LA(1); - if (_la==UTF_ENCODING_BOM) { + switch ( getInterpreter().adaptivePredict(_input,0,_ctx) ) { + case 1: { setState(42); match(UTF_ENCODING_BOM); } + break; } - setState(45); prolog(); setState(47); _errHandler.sync(this); - _la = _input.LA(1); - if (_la==OPEN) { + switch ( getInterpreter().adaptivePredict(_input,1,_ctx) ) { + case 1: { setState(46); element(); } + break; } - } } catch (RecognitionException re) { @@ -238,34 +237,35 @@ public T accept(ParseTreeVisitor visitor) { public final PrologContext prolog() throws RecognitionException { PrologContext _localctx = new PrologContext(_ctx, getState()); enterRule(_localctx, 2, RULE_prolog); - int _la; try { int _alt; enterOuterAlt(_localctx, 1); { setState(50); _errHandler.sync(this); - _la = _input.LA(1); - if (_la==SPECIAL_OPEN_XML) { + switch ( getInterpreter().adaptivePredict(_input,2,_ctx) ) { + case 1: { setState(49); xmldecl(); } + break; } - setState(55); _errHandler.sync(this); - _la = _input.LA(1); - while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 61444L) != 0)) { - { - { - setState(52); - misc(); - } + _alt = getInterpreter().adaptivePredict(_input,3,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(52); + misc(); + } + } } setState(57); _errHandler.sync(this); - _la = _input.LA(1); + _alt = getInterpreter().adaptivePredict(_input,3,_ctx); } setState(61); _errHandler.sync(this); @@ -993,72 +993,67 @@ public final ContentContext content() throws RecognitionException { { setState(153); _errHandler.sync(this); - switch (_input.LA(1)) { - case OPEN: + switch ( getInterpreter().adaptivePredict(_input,17,_ctx) ) { + case 1: { setState(143); element(); } break; - case EntityRef: - case CharRef: + case 2: { setState(144); reference(); } break; - case SPECIAL_OPEN: + case 3: { setState(145); processinginstruction(); } break; - case CDATA: + case 4: { setState(146); match(CDATA); } break; - case COMMENT: + case 5: { setState(147); match(COMMENT); } break; - case JSP_SCRIPTLET: + case 6: { setState(148); jspscriptlet(); } break; - case JSP_EXPRESSION: + case 7: { setState(149); jspexpression(); } break; - case JSP_DECLARATION: + case 8: { setState(150); jspdeclaration(); } break; - case JSP_COMMENT: + case 9: { setState(151); jspcomment(); } break; - case SEA_WS: - case QUESTION_MARK: - case TEXT: + case 10: { setState(152); chardata(); } break; - default: - throw new NoViableAltException(this); } } } @@ -1080,31 +1075,31 @@ public static class ElementContext extends ParserRuleContext { public TerminalNode OPEN(int i) { return getToken(XMLParser.OPEN, i); } - public List Name() { return getTokens(XMLParser.Name); } - public TerminalNode Name(int i) { - return getToken(XMLParser.Name, i); - } - public TerminalNode SLASH_CLOSE() { return getToken(XMLParser.SLASH_CLOSE, 0); } public List CLOSE() { return getTokens(XMLParser.CLOSE); } public TerminalNode CLOSE(int i) { return getToken(XMLParser.CLOSE, i); } + public TerminalNode SLASH() { return getToken(XMLParser.SLASH, 0); } + public List Name() { return getTokens(XMLParser.Name); } + public TerminalNode Name(int i) { + return getToken(XMLParser.Name, i); + } public List attribute() { return getRuleContexts(AttributeContext.class); } public AttributeContext attribute(int i) { return getRuleContext(AttributeContext.class,i); } - public VoidCloseContext voidClose() { - return getRuleContext(VoidCloseContext.class,0); - } - public TerminalNode SLASH() { return getToken(XMLParser.SLASH, 0); } public List content() { return getRuleContexts(ContentContext.class); } public ContentContext content(int i) { return getRuleContext(ContentContext.class,i); } + public TerminalNode SLASH_CLOSE() { return getToken(XMLParser.SLASH_CLOSE, 0); } + public VoidCloseContext voidClose() { + return getRuleContext(VoidCloseContext.class,0); + } public ElementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -1130,84 +1125,170 @@ public final ElementContext element() throws RecognitionException { int _la; try { int _alt; - enterOuterAlt(_localctx, 1); - { - setState(155); - match(OPEN); - setState(156); - ((ElementContext)_localctx).name = match(Name); - setState(160); + setState(212); _errHandler.sync(this); - _la = _input.LA(1); - while (_la==Name) { - { + switch ( getInterpreter().adaptivePredict(_input,25,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); { + setState(155); + if (!(!isHtmlMode())) throw new FailedPredicateException(this, "!isHtmlMode()"); + setState(156); + match(OPEN); setState(157); - attribute(); + ((ElementContext)_localctx).name = match(Name); + setState(161); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==Name) { + { + { + setState(158); + attribute(); + } + } + setState(163); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(164); + match(CLOSE); + setState(168); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,19,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(165); + content(); + } + } + } + setState(170); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,19,_ctx); } + setState(171); + match(OPEN); + setState(172); + match(SLASH); + setState(173); + match(Name); + setState(174); + match(CLOSE); } - setState(162); + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(175); + if (!(!isHtmlMode())) throw new FailedPredicateException(this, "!isHtmlMode()"); + setState(176); + match(OPEN); + setState(177); + ((ElementContext)_localctx).name = match(Name); + setState(181); _errHandler.sync(this); _la = _input.LA(1); - } - setState(179); - _errHandler.sync(this); - switch (_input.LA(1)) { - case SLASH_CLOSE: - { - setState(163); + while (_la==Name) { + { + { + setState(178); + attribute(); + } + } + setState(183); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(184); match(SLASH_CLOSE); } break; - case CLOSE: + case 3: + enterOuterAlt(_localctx, 3); { - setState(164); - match(CLOSE); - setState(177); + setState(185); + if (!(isHtmlMode())) throw new FailedPredicateException(this, "isHtmlMode()"); + setState(186); + match(OPEN); + setState(187); + ((ElementContext)_localctx).name = match(Name); + setState(191); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==Name) { + { + { + setState(188); + attribute(); + } + } + setState(193); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(210); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,20,_ctx) ) { - case 1: + switch (_input.LA(1)) { + case SLASH_CLOSE: { - setState(165); - if (!(isVoidElement((((ElementContext)_localctx).name!=null?((ElementContext)_localctx).name.getText():null)))) throw new FailedPredicateException(this, "isVoidElement($name.text)"); - setState(166); - voidClose(); + setState(194); + match(SLASH_CLOSE); } break; - case 2: + case CLOSE: { - setState(170); + setState(195); + match(CLOSE); + setState(208); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,19,_ctx); - while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { - if ( _alt==1 ) { - { - { - setState(167); - content(); - } - } + switch ( getInterpreter().adaptivePredict(_input,23,_ctx) ) { + case 1: + { + setState(196); + if (!(isVoidElement((((ElementContext)_localctx).name!=null?((ElementContext)_localctx).name.getText():null)))) throw new FailedPredicateException(this, "isVoidElement($name.text)"); + setState(197); + voidClose(); } - setState(172); + break; + case 2: + { + setState(201); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,19,_ctx); + _alt = getInterpreter().adaptivePredict(_input,22,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(198); + content(); + } + } + } + setState(203); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,22,_ctx); + } + setState(204); + match(OPEN); + setState(205); + match(SLASH); + setState(206); + match(Name); + setState(207); + match(CLOSE); + } + break; } - setState(173); - match(OPEN); - setState(174); - match(SLASH); - setState(175); - match(Name); - setState(176); - match(CLOSE); } break; + default: + throw new NoViableAltException(this); } } break; - default: - throw new NoViableAltException(this); - } } } catch (RecognitionException re) { @@ -1300,29 +1381,29 @@ public final JspdirectiveContext jspdirective() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(183); + setState(216); match(OPEN); - setState(184); + setState(217); match(DIRECTIVE_OPEN); - setState(185); + setState(218); match(Name); - setState(189); + setState(222); _errHandler.sync(this); _la = _input.LA(1); while (_la==Name) { { { - setState(186); + setState(219); attribute(); } } - setState(191); + setState(224); _errHandler.sync(this); _la = _input.LA(1); } - setState(192); + setState(225); match(DIRECTIVE_CLOSE); - setState(193); + setState(226); match(CLOSE); } } @@ -1365,7 +1446,7 @@ public final JspscriptletContext jspscriptlet() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(195); + setState(228); match(JSP_SCRIPTLET); } } @@ -1408,7 +1489,7 @@ public final JspexpressionContext jspexpression() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(197); + setState(230); match(JSP_EXPRESSION); } } @@ -1451,7 +1532,7 @@ public final JspdeclarationContext jspdeclaration() throws RecognitionException try { enterOuterAlt(_localctx, 1); { - setState(199); + setState(232); match(JSP_DECLARATION); } } @@ -1494,7 +1575,7 @@ public final JspcommentContext jspcomment() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(201); + setState(234); match(JSP_COMMENT); } } @@ -1539,7 +1620,7 @@ public final ReferenceContext reference() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(203); + setState(236); _la = _input.LA(1); if ( !(_la==EntityRef || _la==CharRef) ) { _errHandler.recoverInline(this); @@ -1592,11 +1673,11 @@ public final AttributeContext attribute() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(205); + setState(238); match(Name); - setState(206); + setState(239); match(EQUALS); - setState(207); + setState(240); match(STRING); } } @@ -1642,7 +1723,7 @@ public final ChardataContext chardata() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(209); + setState(242); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 262784L) != 0)) ) { _errHandler.recoverInline(this); @@ -1675,13 +1756,19 @@ public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { private boolean element_sempred(ElementContext _localctx, int predIndex) { switch (predIndex) { case 0: + return !isHtmlMode(); + case 1: + return !isHtmlMode(); + case 2: + return isHtmlMode(); + case 3: return isVoidElement((((ElementContext)_localctx).name!=null?((ElementContext)_localctx).name.getText():null)); } return true; } public static final String _serializedATN = - "\u0004\u0001*\u00d4\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ + "\u0004\u0001*\u00f5\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ "\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004\u0002"+ "\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007\u0002"+ "\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b\u0007\u000b\u0002"+ @@ -1704,114 +1791,138 @@ private boolean element_sempred(ElementContext _localctx, int predIndex) { "\b\u0003\b\u0085\b\b\u0001\t\u0001\t\u0005\t\u0089\b\t\n\t\f\t\u008c\t"+ "\t\u0001\t\u0001\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001"+ "\n\u0001\n\u0001\n\u0001\n\u0003\n\u009a\b\n\u0001\u000b\u0001\u000b\u0001"+ - "\u000b\u0005\u000b\u009f\b\u000b\n\u000b\f\u000b\u00a2\t\u000b\u0001\u000b"+ - "\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0005\u000b\u00a9\b\u000b"+ - "\n\u000b\f\u000b\u00ac\t\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001"+ - "\u000b\u0003\u000b\u00b2\b\u000b\u0003\u000b\u00b4\b\u000b\u0001\f\u0001"+ - "\f\u0001\r\u0001\r\u0001\r\u0001\r\u0005\r\u00bc\b\r\n\r\f\r\u00bf\t\r"+ - "\u0001\r\u0001\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f"+ - "\u0001\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001\u0012\u0001\u0012"+ - "\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0014\u0001\u0014"+ - "\u0001\u0014\u0000\u0000\u0015\u0000\u0002\u0004\u0006\b\n\f\u000e\u0010"+ - "\u0012\u0014\u0016\u0018\u001a\u001c\u001e \"$&(\u0000\u0003\u0001\u0000"+ - "\u001c\u001d\u0001\u0000\u0005\u0006\u0003\u0000\u0007\u0007\t\t\u0012"+ - "\u0012\u00e1\u0000+\u0001\u0000\u0000\u0000\u00022\u0001\u0000\u0000\u0000"+ - "\u0004@\u0001\u0000\u0000\u0000\u0006N\u0001\u0000\u0000\u0000\bP\u0001"+ - "\u0000\u0000\u0000\nf\u0001\u0000\u0000\u0000\f\u007f\u0001\u0000\u0000"+ - "\u0000\u000e\u0081\u0001\u0000\u0000\u0000\u0010\u0084\u0001\u0000\u0000"+ - "\u0000\u0012\u0086\u0001\u0000\u0000\u0000\u0014\u0099\u0001\u0000\u0000"+ - "\u0000\u0016\u009b\u0001\u0000\u0000\u0000\u0018\u00b5\u0001\u0000\u0000"+ - "\u0000\u001a\u00b7\u0001\u0000\u0000\u0000\u001c\u00c3\u0001\u0000\u0000"+ - "\u0000\u001e\u00c5\u0001\u0000\u0000\u0000 \u00c7\u0001\u0000\u0000\u0000"+ - "\"\u00c9\u0001\u0000\u0000\u0000$\u00cb\u0001\u0000\u0000\u0000&\u00cd"+ - "\u0001\u0000\u0000\u0000(\u00d1\u0001\u0000\u0000\u0000*,\u0005\b\u0000"+ - "\u0000+*\u0001\u0000\u0000\u0000+,\u0001\u0000\u0000\u0000,-\u0001\u0000"+ - "\u0000\u0000-/\u0003\u0002\u0001\u0000.0\u0003\u0016\u000b\u0000/.\u0001"+ - "\u0000\u0000\u0000/0\u0001\u0000\u0000\u00000\u0001\u0001\u0000\u0000"+ - "\u000013\u0003\u0004\u0002\u000021\u0001\u0000\u0000\u000023\u0001\u0000"+ - "\u0000\u000037\u0001\u0000\u0000\u000046\u0003\u0006\u0003\u000054\u0001"+ - "\u0000\u0000\u000069\u0001\u0000\u0000\u000075\u0001\u0000\u0000\u0000"+ - "78\u0001\u0000\u0000\u00008=\u0001\u0000\u0000\u000097\u0001\u0000\u0000"+ - "\u0000:<\u0003\u001a\r\u0000;:\u0001\u0000\u0000\u0000\u0001\u0000\u0000\u0000>\u0003\u0001"+ - "\u0000\u0000\u0000?=\u0001\u0000\u0000\u0000@D\u0005\n\u0000\u0000AC\u0003"+ - "&\u0013\u0000BA\u0001\u0000\u0000\u0000CF\u0001\u0000\u0000\u0000DB\u0001"+ - "\u0000\u0000\u0000DE\u0001\u0000\u0000\u0000EG\u0001\u0000\u0000\u0000"+ - "FD\u0001\u0000\u0000\u0000GH\u0005\"\u0000\u0000H\u0005\u0001\u0000\u0000"+ - "\u0000IO\u0005\u0002\u0000\u0000JO\u0003\b\u0004\u0000KO\u0003\u0012\t"+ - "\u0000LO\u0003 \u0010\u0000MO\u0003\"\u0011\u0000NI\u0001\u0000\u0000"+ - "\u0000NJ\u0001\u0000\u0000\u0000NK\u0001\u0000\u0000\u0000NL\u0001\u0000"+ - "\u0000\u0000NM\u0001\u0000\u0000\u0000O\u0007\u0001\u0000\u0000\u0000"+ - "PQ\u0005\r\u0000\u0000QR\u0005\u0016\u0000\u0000RS\u0005*\u0000\u0000"+ - "SW\u0003\u0010\b\u0000TV\u0005)\u0000\u0000UT\u0001\u0000\u0000\u0000"+ - "VY\u0001\u0000\u0000\u0000WU\u0001\u0000\u0000\u0000WX\u0001\u0000\u0000"+ - "\u0000X^\u0001\u0000\u0000\u0000YW\u0001\u0000\u0000\u0000Z[\u0005\u0014"+ - "\u0000\u0000[\\\u0003\n\u0005\u0000\\]\u0005\u0017\u0000\u0000]_\u0001"+ - "\u0000\u0000\u0000^Z\u0001\u0000\u0000\u0000^_\u0001\u0000\u0000\u0000"+ - "_`\u0001\u0000\u0000\u0000`a\u0005\u0013\u0000\u0000a\t\u0001\u0000\u0000"+ - "\u0000be\u0003\f\u0006\u0000ce\u0003\u000e\u0007\u0000db\u0001\u0000\u0000"+ - "\u0000dc\u0001\u0000\u0000\u0000eh\u0001\u0000\u0000\u0000fd\u0001\u0000"+ - "\u0000\u0000fg\u0001\u0000\u0000\u0000g\u000b\u0001\u0000\u0000\u0000"+ - "hf\u0001\u0000\u0000\u0000im\u0005\u0018\u0000\u0000jl\u0007\u0000\u0000"+ - "\u0000kj\u0001\u0000\u0000\u0000lo\u0001\u0000\u0000\u0000mk\u0001\u0000"+ - "\u0000\u0000mn\u0001\u0000\u0000\u0000ns\u0001\u0000\u0000\u0000om\u0001"+ - "\u0000\u0000\u0000pr\u0005\u001e\u0000\u0000qp\u0001\u0000\u0000\u0000"+ - "ru\u0001\u0000\u0000\u0000sq\u0001\u0000\u0000\u0000st\u0001\u0000\u0000"+ - "\u0000ty\u0001\u0000\u0000\u0000us\u0001\u0000\u0000\u0000vx\u0007\u0000"+ - "\u0000\u0000wv\u0001\u0000\u0000\u0000x{\u0001\u0000\u0000\u0000yw\u0001"+ - "\u0000\u0000\u0000yz\u0001\u0000\u0000\u0000z|\u0001\u0000\u0000\u0000"+ - "{y\u0001\u0000\u0000\u0000|\u0080\u0005\u001a\u0000\u0000}\u0080\u0003"+ - "\u0012\t\u0000~\u0080\u0005\u0002\u0000\u0000\u007fi\u0001\u0000\u0000"+ - "\u0000\u007f}\u0001\u0000\u0000\u0000\u007f~\u0001\u0000\u0000\u0000\u0080"+ - "\r\u0001\u0000\u0000\u0000\u0081\u0082\u0005\u0004\u0000\u0000\u0082\u000f"+ - "\u0001\u0000\u0000\u0000\u0083\u0085\u0005*\u0000\u0000\u0084\u0083\u0001"+ - "\u0000\u0000\u0000\u0084\u0085\u0001\u0000\u0000\u0000\u0085\u0011\u0001"+ - "\u0000\u0000\u0000\u0086\u008a\u0005\f\u0000\u0000\u0087\u0089\u0005 "+ - "\u0000\u0000\u0088\u0087\u0001\u0000\u0000\u0000\u0089\u008c\u0001\u0000"+ - "\u0000\u0000\u008a\u0088\u0001\u0000\u0000\u0000\u008a\u008b\u0001\u0000"+ - "\u0000\u0000\u008b\u008d\u0001\u0000\u0000\u0000\u008c\u008a\u0001\u0000"+ - "\u0000\u0000\u008d\u008e\u0005\"\u0000\u0000\u008e\u0013\u0001\u0000\u0000"+ - "\u0000\u008f\u009a\u0003\u0016\u000b\u0000\u0090\u009a\u0003$\u0012\u0000"+ - "\u0091\u009a\u0003\u0012\t\u0000\u0092\u009a\u0005\u0003\u0000\u0000\u0093"+ - "\u009a\u0005\u0002\u0000\u0000\u0094\u009a\u0003\u001c\u000e\u0000\u0095"+ - "\u009a\u0003\u001e\u000f\u0000\u0096\u009a\u0003 \u0010\u0000\u0097\u009a"+ - "\u0003\"\u0011\u0000\u0098\u009a\u0003(\u0014\u0000\u0099\u008f\u0001"+ - "\u0000\u0000\u0000\u0099\u0090\u0001\u0000\u0000\u0000\u0099\u0091\u0001"+ - "\u0000\u0000\u0000\u0099\u0092\u0001\u0000\u0000\u0000\u0099\u0093\u0001"+ - "\u0000\u0000\u0000\u0099\u0094\u0001\u0000\u0000\u0000\u0099\u0095\u0001"+ - "\u0000\u0000\u0000\u0099\u0096\u0001\u0000\u0000\u0000\u0099\u0097\u0001"+ - "\u0000\u0000\u0000\u0099\u0098\u0001\u0000\u0000\u0000\u009a\u0015\u0001"+ - "\u0000\u0000\u0000\u009b\u009c\u0005\u000b\u0000\u0000\u009c\u00a0\u0005"+ - "*\u0000\u0000\u009d\u009f\u0003&\u0013\u0000\u009e\u009d\u0001\u0000\u0000"+ - "\u0000\u009f\u00a2\u0001\u0000\u0000\u0000\u00a0\u009e\u0001\u0000\u0000"+ - "\u0000\u00a0\u00a1\u0001\u0000\u0000\u0000\u00a1\u00b3\u0001\u0000\u0000"+ - "\u0000\u00a2\u00a0\u0001\u0000\u0000\u0000\u00a3\u00b4\u0005#\u0000\u0000"+ - "\u00a4\u00b1\u0005!\u0000\u0000\u00a5\u00a6\u0004\u000b\u0000\u0001\u00a6"+ - "\u00b2\u0003\u0018\f\u0000\u00a7\u00a9\u0003\u0014\n\u0000\u00a8\u00a7"+ - "\u0001\u0000\u0000\u0000\u00a9\u00ac\u0001\u0000\u0000\u0000\u00aa\u00a8"+ - "\u0001\u0000\u0000\u0000\u00aa\u00ab\u0001\u0000\u0000\u0000\u00ab\u00ad"+ - "\u0001\u0000\u0000\u0000\u00ac\u00aa\u0001\u0000\u0000\u0000\u00ad\u00ae"+ - "\u0005\u000b\u0000\u0000\u00ae\u00af\u0005\'\u0000\u0000\u00af\u00b0\u0005"+ - "*\u0000\u0000\u00b0\u00b2\u0005!\u0000\u0000\u00b1\u00a5\u0001\u0000\u0000"+ - "\u0000\u00b1\u00aa\u0001\u0000\u0000\u0000\u00b2\u00b4\u0001\u0000\u0000"+ - "\u0000\u00b3\u00a3\u0001\u0000\u0000\u0000\u00b3\u00a4\u0001\u0000\u0000"+ - "\u0000\u00b4\u0017\u0001\u0000\u0000\u0000\u00b5\u00b6\u0001\u0000\u0000"+ - "\u0000\u00b6\u0019\u0001\u0000\u0000\u0000\u00b7\u00b8\u0005\u000b\u0000"+ - "\u0000\u00b8\u00b9\u0005%\u0000\u0000\u00b9\u00bd\u0005*\u0000\u0000\u00ba"+ - "\u00bc\u0003&\u0013\u0000\u00bb\u00ba\u0001\u0000\u0000\u0000\u00bc\u00bf"+ - "\u0001\u0000\u0000\u0000\u00bd\u00bb\u0001\u0000\u0000\u0000\u00bd\u00be"+ - "\u0001\u0000\u0000\u0000\u00be\u00c0\u0001\u0000\u0000\u0000\u00bf\u00bd"+ - "\u0001\u0000\u0000\u0000\u00c0\u00c1\u0005&\u0000\u0000\u00c1\u00c2\u0005"+ - "!\u0000\u0000\u00c2\u001b\u0001\u0000\u0000\u0000\u00c3\u00c4\u0005\u0011"+ - "\u0000\u0000\u00c4\u001d\u0001\u0000\u0000\u0000\u00c5\u00c6\u0005\u0010"+ - "\u0000\u0000\u00c6\u001f\u0001\u0000\u0000\u0000\u00c7\u00c8\u0005\u000f"+ - "\u0000\u0000\u00c8!\u0001\u0000\u0000\u0000\u00c9\u00ca\u0005\u000e\u0000"+ - "\u0000\u00ca#\u0001\u0000\u0000\u0000\u00cb\u00cc\u0007\u0001\u0000\u0000"+ - "\u00cc%\u0001\u0000\u0000\u0000\u00cd\u00ce\u0005*\u0000\u0000\u00ce\u00cf"+ - "\u0005(\u0000\u0000\u00cf\u00d0\u0005)\u0000\u0000\u00d0\'\u0001\u0000"+ - "\u0000\u0000\u00d1\u00d2\u0007\u0002\u0000\u0000\u00d2)\u0001\u0000\u0000"+ - "\u0000\u0017+/27=DNW^dfmsy\u007f\u0084\u008a\u0099\u00a0\u00aa\u00b1\u00b3"+ - "\u00bd"; + "\u000b\u0001\u000b\u0005\u000b\u00a0\b\u000b\n\u000b\f\u000b\u00a3\t\u000b"+ + "\u0001\u000b\u0001\u000b\u0005\u000b\u00a7\b\u000b\n\u000b\f\u000b\u00aa"+ + "\t\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001"+ + "\u000b\u0001\u000b\u0001\u000b\u0005\u000b\u00b4\b\u000b\n\u000b\f\u000b"+ + "\u00b7\t\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b"+ + "\u0005\u000b\u00be\b\u000b\n\u000b\f\u000b\u00c1\t\u000b\u0001\u000b\u0001"+ + "\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0005\u000b\u00c8\b\u000b\n"+ + "\u000b\f\u000b\u00cb\t\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001"+ + "\u000b\u0003\u000b\u00d1\b\u000b\u0003\u000b\u00d3\b\u000b\u0003\u000b"+ + "\u00d5\b\u000b\u0001\f\u0001\f\u0001\r\u0001\r\u0001\r\u0001\r\u0005\r"+ + "\u00dd\b\r\n\r\f\r\u00e0\t\r\u0001\r\u0001\r\u0001\r\u0001\u000e\u0001"+ + "\u000e\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001\u0011\u0001"+ + "\u0011\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001\u0013\u0001"+ + "\u0013\u0001\u0014\u0001\u0014\u0001\u0014\u0000\u0000\u0015\u0000\u0002"+ + "\u0004\u0006\b\n\f\u000e\u0010\u0012\u0014\u0016\u0018\u001a\u001c\u001e"+ + " \"$&(\u0000\u0003\u0001\u0000\u001c\u001d\u0001\u0000\u0005\u0006\u0003"+ + "\u0000\u0007\u0007\t\t\u0012\u0012\u0107\u0000+\u0001\u0000\u0000\u0000"+ + "\u00022\u0001\u0000\u0000\u0000\u0004@\u0001\u0000\u0000\u0000\u0006N"+ + "\u0001\u0000\u0000\u0000\bP\u0001\u0000\u0000\u0000\nf\u0001\u0000\u0000"+ + "\u0000\f\u007f\u0001\u0000\u0000\u0000\u000e\u0081\u0001\u0000\u0000\u0000"+ + "\u0010\u0084\u0001\u0000\u0000\u0000\u0012\u0086\u0001\u0000\u0000\u0000"+ + "\u0014\u0099\u0001\u0000\u0000\u0000\u0016\u00d4\u0001\u0000\u0000\u0000"+ + "\u0018\u00d6\u0001\u0000\u0000\u0000\u001a\u00d8\u0001\u0000\u0000\u0000"+ + "\u001c\u00e4\u0001\u0000\u0000\u0000\u001e\u00e6\u0001\u0000\u0000\u0000"+ + " \u00e8\u0001\u0000\u0000\u0000\"\u00ea\u0001\u0000\u0000\u0000$\u00ec"+ + "\u0001\u0000\u0000\u0000&\u00ee\u0001\u0000\u0000\u0000(\u00f2\u0001\u0000"+ + "\u0000\u0000*,\u0005\b\u0000\u0000+*\u0001\u0000\u0000\u0000+,\u0001\u0000"+ + "\u0000\u0000,-\u0001\u0000\u0000\u0000-/\u0003\u0002\u0001\u0000.0\u0003"+ + "\u0016\u000b\u0000/.\u0001\u0000\u0000\u0000/0\u0001\u0000\u0000\u0000"+ + "0\u0001\u0001\u0000\u0000\u000013\u0003\u0004\u0002\u000021\u0001\u0000"+ + "\u0000\u000023\u0001\u0000\u0000\u000037\u0001\u0000\u0000\u000046\u0003"+ + "\u0006\u0003\u000054\u0001\u0000\u0000\u000069\u0001\u0000\u0000\u0000"+ + "75\u0001\u0000\u0000\u000078\u0001\u0000\u0000\u00008=\u0001\u0000\u0000"+ + "\u000097\u0001\u0000\u0000\u0000:<\u0003\u001a\r\u0000;:\u0001\u0000\u0000"+ + "\u0000\u0001\u0000"+ + "\u0000\u0000>\u0003\u0001\u0000\u0000\u0000?=\u0001\u0000\u0000\u0000"+ + "@D\u0005\n\u0000\u0000AC\u0003&\u0013\u0000BA\u0001\u0000\u0000\u0000"+ + "CF\u0001\u0000\u0000\u0000DB\u0001\u0000\u0000\u0000DE\u0001\u0000\u0000"+ + "\u0000EG\u0001\u0000\u0000\u0000FD\u0001\u0000\u0000\u0000GH\u0005\"\u0000"+ + "\u0000H\u0005\u0001\u0000\u0000\u0000IO\u0005\u0002\u0000\u0000JO\u0003"+ + "\b\u0004\u0000KO\u0003\u0012\t\u0000LO\u0003 \u0010\u0000MO\u0003\"\u0011"+ + "\u0000NI\u0001\u0000\u0000\u0000NJ\u0001\u0000\u0000\u0000NK\u0001\u0000"+ + "\u0000\u0000NL\u0001\u0000\u0000\u0000NM\u0001\u0000\u0000\u0000O\u0007"+ + "\u0001\u0000\u0000\u0000PQ\u0005\r\u0000\u0000QR\u0005\u0016\u0000\u0000"+ + "RS\u0005*\u0000\u0000SW\u0003\u0010\b\u0000TV\u0005)\u0000\u0000UT\u0001"+ + "\u0000\u0000\u0000VY\u0001\u0000\u0000\u0000WU\u0001\u0000\u0000\u0000"+ + "WX\u0001\u0000\u0000\u0000X^\u0001\u0000\u0000\u0000YW\u0001\u0000\u0000"+ + "\u0000Z[\u0005\u0014\u0000\u0000[\\\u0003\n\u0005\u0000\\]\u0005\u0017"+ + "\u0000\u0000]_\u0001\u0000\u0000\u0000^Z\u0001\u0000\u0000\u0000^_\u0001"+ + "\u0000\u0000\u0000_`\u0001\u0000\u0000\u0000`a\u0005\u0013\u0000\u0000"+ + "a\t\u0001\u0000\u0000\u0000be\u0003\f\u0006\u0000ce\u0003\u000e\u0007"+ + "\u0000db\u0001\u0000\u0000\u0000dc\u0001\u0000\u0000\u0000eh\u0001\u0000"+ + "\u0000\u0000fd\u0001\u0000\u0000\u0000fg\u0001\u0000\u0000\u0000g\u000b"+ + "\u0001\u0000\u0000\u0000hf\u0001\u0000\u0000\u0000im\u0005\u0018\u0000"+ + "\u0000jl\u0007\u0000\u0000\u0000kj\u0001\u0000\u0000\u0000lo\u0001\u0000"+ + "\u0000\u0000mk\u0001\u0000\u0000\u0000mn\u0001\u0000\u0000\u0000ns\u0001"+ + "\u0000\u0000\u0000om\u0001\u0000\u0000\u0000pr\u0005\u001e\u0000\u0000"+ + "qp\u0001\u0000\u0000\u0000ru\u0001\u0000\u0000\u0000sq\u0001\u0000\u0000"+ + "\u0000st\u0001\u0000\u0000\u0000ty\u0001\u0000\u0000\u0000us\u0001\u0000"+ + "\u0000\u0000vx\u0007\u0000\u0000\u0000wv\u0001\u0000\u0000\u0000x{\u0001"+ + "\u0000\u0000\u0000yw\u0001\u0000\u0000\u0000yz\u0001\u0000\u0000\u0000"+ + "z|\u0001\u0000\u0000\u0000{y\u0001\u0000\u0000\u0000|\u0080\u0005\u001a"+ + "\u0000\u0000}\u0080\u0003\u0012\t\u0000~\u0080\u0005\u0002\u0000\u0000"+ + "\u007fi\u0001\u0000\u0000\u0000\u007f}\u0001\u0000\u0000\u0000\u007f~"+ + "\u0001\u0000\u0000\u0000\u0080\r\u0001\u0000\u0000\u0000\u0081\u0082\u0005"+ + "\u0004\u0000\u0000\u0082\u000f\u0001\u0000\u0000\u0000\u0083\u0085\u0005"+ + "*\u0000\u0000\u0084\u0083\u0001\u0000\u0000\u0000\u0084\u0085\u0001\u0000"+ + "\u0000\u0000\u0085\u0011\u0001\u0000\u0000\u0000\u0086\u008a\u0005\f\u0000"+ + "\u0000\u0087\u0089\u0005 \u0000\u0000\u0088\u0087\u0001\u0000\u0000\u0000"+ + "\u0089\u008c\u0001\u0000\u0000\u0000\u008a\u0088\u0001\u0000\u0000\u0000"+ + "\u008a\u008b\u0001\u0000\u0000\u0000\u008b\u008d\u0001\u0000\u0000\u0000"+ + "\u008c\u008a\u0001\u0000\u0000\u0000\u008d\u008e\u0005\"\u0000\u0000\u008e"+ + "\u0013\u0001\u0000\u0000\u0000\u008f\u009a\u0003\u0016\u000b\u0000\u0090"+ + "\u009a\u0003$\u0012\u0000\u0091\u009a\u0003\u0012\t\u0000\u0092\u009a"+ + "\u0005\u0003\u0000\u0000\u0093\u009a\u0005\u0002\u0000\u0000\u0094\u009a"+ + "\u0003\u001c\u000e\u0000\u0095\u009a\u0003\u001e\u000f\u0000\u0096\u009a"+ + "\u0003 \u0010\u0000\u0097\u009a\u0003\"\u0011\u0000\u0098\u009a\u0003"+ + "(\u0014\u0000\u0099\u008f\u0001\u0000\u0000\u0000\u0099\u0090\u0001\u0000"+ + "\u0000\u0000\u0099\u0091\u0001\u0000\u0000\u0000\u0099\u0092\u0001\u0000"+ + "\u0000\u0000\u0099\u0093\u0001\u0000\u0000\u0000\u0099\u0094\u0001\u0000"+ + "\u0000\u0000\u0099\u0095\u0001\u0000\u0000\u0000\u0099\u0096\u0001\u0000"+ + "\u0000\u0000\u0099\u0097\u0001\u0000\u0000\u0000\u0099\u0098\u0001\u0000"+ + "\u0000\u0000\u009a\u0015\u0001\u0000\u0000\u0000\u009b\u009c\u0004\u000b"+ + "\u0000\u0000\u009c\u009d\u0005\u000b\u0000\u0000\u009d\u00a1\u0005*\u0000"+ + "\u0000\u009e\u00a0\u0003&\u0013\u0000\u009f\u009e\u0001\u0000\u0000\u0000"+ + "\u00a0\u00a3\u0001\u0000\u0000\u0000\u00a1\u009f\u0001\u0000\u0000\u0000"+ + "\u00a1\u00a2\u0001\u0000\u0000\u0000\u00a2\u00a4\u0001\u0000\u0000\u0000"+ + "\u00a3\u00a1\u0001\u0000\u0000\u0000\u00a4\u00a8\u0005!\u0000\u0000\u00a5"+ + "\u00a7\u0003\u0014\n\u0000\u00a6\u00a5\u0001\u0000\u0000\u0000\u00a7\u00aa"+ + "\u0001\u0000\u0000\u0000\u00a8\u00a6\u0001\u0000\u0000\u0000\u00a8\u00a9"+ + "\u0001\u0000\u0000\u0000\u00a9\u00ab\u0001\u0000\u0000\u0000\u00aa\u00a8"+ + "\u0001\u0000\u0000\u0000\u00ab\u00ac\u0005\u000b\u0000\u0000\u00ac\u00ad"+ + "\u0005\'\u0000\u0000\u00ad\u00ae\u0005*\u0000\u0000\u00ae\u00d5\u0005"+ + "!\u0000\u0000\u00af\u00b0\u0004\u000b\u0001\u0000\u00b0\u00b1\u0005\u000b"+ + "\u0000\u0000\u00b1\u00b5\u0005*\u0000\u0000\u00b2\u00b4\u0003&\u0013\u0000"+ + "\u00b3\u00b2\u0001\u0000\u0000\u0000\u00b4\u00b7\u0001\u0000\u0000\u0000"+ + "\u00b5\u00b3\u0001\u0000\u0000\u0000\u00b5\u00b6\u0001\u0000\u0000\u0000"+ + "\u00b6\u00b8\u0001\u0000\u0000\u0000\u00b7\u00b5\u0001\u0000\u0000\u0000"+ + "\u00b8\u00d5\u0005#\u0000\u0000\u00b9\u00ba\u0004\u000b\u0002\u0000\u00ba"+ + "\u00bb\u0005\u000b\u0000\u0000\u00bb\u00bf\u0005*\u0000\u0000\u00bc\u00be"+ + "\u0003&\u0013\u0000\u00bd\u00bc\u0001\u0000\u0000\u0000\u00be\u00c1\u0001"+ + "\u0000\u0000\u0000\u00bf\u00bd\u0001\u0000\u0000\u0000\u00bf\u00c0\u0001"+ + "\u0000\u0000\u0000\u00c0\u00d2\u0001\u0000\u0000\u0000\u00c1\u00bf\u0001"+ + "\u0000\u0000\u0000\u00c2\u00d3\u0005#\u0000\u0000\u00c3\u00d0\u0005!\u0000"+ + "\u0000\u00c4\u00c5\u0004\u000b\u0003\u0001\u00c5\u00d1\u0003\u0018\f\u0000"+ + "\u00c6\u00c8\u0003\u0014\n\u0000\u00c7\u00c6\u0001\u0000\u0000\u0000\u00c8"+ + "\u00cb\u0001\u0000\u0000\u0000\u00c9\u00c7\u0001\u0000\u0000\u0000\u00c9"+ + "\u00ca\u0001\u0000\u0000\u0000\u00ca\u00cc\u0001\u0000\u0000\u0000\u00cb"+ + "\u00c9\u0001\u0000\u0000\u0000\u00cc\u00cd\u0005\u000b\u0000\u0000\u00cd"+ + "\u00ce\u0005\'\u0000\u0000\u00ce\u00cf\u0005*\u0000\u0000\u00cf\u00d1"+ + "\u0005!\u0000\u0000\u00d0\u00c4\u0001\u0000\u0000\u0000\u00d0\u00c9\u0001"+ + "\u0000\u0000\u0000\u00d1\u00d3\u0001\u0000\u0000\u0000\u00d2\u00c2\u0001"+ + "\u0000\u0000\u0000\u00d2\u00c3\u0001\u0000\u0000\u0000\u00d3\u00d5\u0001"+ + "\u0000\u0000\u0000\u00d4\u009b\u0001\u0000\u0000\u0000\u00d4\u00af\u0001"+ + "\u0000\u0000\u0000\u00d4\u00b9\u0001\u0000\u0000\u0000\u00d5\u0017\u0001"+ + "\u0000\u0000\u0000\u00d6\u00d7\u0001\u0000\u0000\u0000\u00d7\u0019\u0001"+ + "\u0000\u0000\u0000\u00d8\u00d9\u0005\u000b\u0000\u0000\u00d9\u00da\u0005"+ + "%\u0000\u0000\u00da\u00de\u0005*\u0000\u0000\u00db\u00dd\u0003&\u0013"+ + "\u0000\u00dc\u00db\u0001\u0000\u0000\u0000\u00dd\u00e0\u0001\u0000\u0000"+ + "\u0000\u00de\u00dc\u0001\u0000\u0000\u0000\u00de\u00df\u0001\u0000\u0000"+ + "\u0000\u00df\u00e1\u0001\u0000\u0000\u0000\u00e0\u00de\u0001\u0000\u0000"+ + "\u0000\u00e1\u00e2\u0005&\u0000\u0000\u00e2\u00e3\u0005!\u0000\u0000\u00e3"+ + "\u001b\u0001\u0000\u0000\u0000\u00e4\u00e5\u0005\u0011\u0000\u0000\u00e5"+ + "\u001d\u0001\u0000\u0000\u0000\u00e6\u00e7\u0005\u0010\u0000\u0000\u00e7"+ + "\u001f\u0001\u0000\u0000\u0000\u00e8\u00e9\u0005\u000f\u0000\u0000\u00e9"+ + "!\u0001\u0000\u0000\u0000\u00ea\u00eb\u0005\u000e\u0000\u0000\u00eb#\u0001"+ + "\u0000\u0000\u0000\u00ec\u00ed\u0007\u0001\u0000\u0000\u00ed%\u0001\u0000"+ + "\u0000\u0000\u00ee\u00ef\u0005*\u0000\u0000\u00ef\u00f0\u0005(\u0000\u0000"+ + "\u00f0\u00f1\u0005)\u0000\u0000\u00f1\'\u0001\u0000\u0000\u0000\u00f2"+ + "\u00f3\u0007\u0002\u0000\u0000\u00f3)\u0001\u0000\u0000\u0000\u001b+/"+ + "27=DNW^dfmsy\u007f\u0084\u008a\u0099\u00a1\u00a8\u00b5\u00bf\u00c9\u00d0"+ + "\u00d2\u00d4\u00de"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParserBase.java b/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParserBase.java index 21eca74350f..32dbec5f419 100644 --- a/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParserBase.java +++ b/rewrite-xml/src/main/java/org/openrewrite/xml/internal/grammar/XMLParserBase.java @@ -45,6 +45,16 @@ protected XMLParserBase(TokenStream input) { super(input); } + /** + * Gates the {@code element} rule so that strict XML keeps the plain two-alternative shape it had before void + * element support was added. The shape of the rule, not just which alternative matches, determines the + * resynchronization sets ANTLR's error recovery uses, so sharing one shape between the two modes would let + * HTML support alter how malformed XML recovers. + */ + public boolean isHtmlMode() { + return htmlMode; + } + public boolean isVoidElement(@Nullable String name) { return htmlMode && name != null && VOID_ELEMENTS.contains(name.toLowerCase()); } diff --git a/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java b/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java index d55a20d2a4c..b21c1e229cb 100755 --- a/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java +++ b/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java @@ -26,6 +26,7 @@ import org.openrewrite.ExecutionContext; import org.openrewrite.InMemoryExecutionContext; import org.openrewrite.Issue; +import org.openrewrite.ParseExceptionResult; import org.openrewrite.Parser.Input; import org.openrewrite.SourceFile; import org.openrewrite.test.RecipeSpec; @@ -957,4 +958,65 @@ void malformedBareAmpersandDoesNotThrow() { assertThat(parsed).isInstanceOf(ParseError.class); assertThat(parsed.printAll()).isEqualTo("McFarland & Company"); } + + @Issue("https://github.com/openrewrite/rewrite/pull/7906") + @Test + void attributeValueWithUnescapedQuoteIsNotGivenAnExtraEquals() { + // The lexer ends a STRING at the first embedded quote, so the rest of the value re-lexes as more + // attributes. Error recovery must not synthesize an '=' for them, because the printer cannot tell a + // synthesized '=' from a real one and writes it back into the value. + SourceFile parsed = XmlParser.builder().build() + .parse(new InMemoryExecutionContext(t -> { + }), "") + .findFirst().orElseThrow(); + assertThat(parsed).isNotInstanceOf(ParseError.class); + assertThat(parsed.printAll()).isEqualTo(""); + } + + @Issue("https://github.com/openrewrite/rewrite/pull/7906") + @Test + void policyExpressionAttributeValueIsNeverRewritten() { + // Multi-line embedded expressions (e.g. Azure API Management policies) routinely carry unescaped + // quotes. Such a document is not well-formed XML, so a ParseError is correct -- but the text must + // come back byte for byte, never with an '=' inserted into a value. + @Language("xml") + String policy = """ + + + + + + """; + SourceFile parsed = XmlParser.builder().build() + .parse(new InMemoryExecutionContext(t -> { + }), policy) + .findFirst().orElseThrow(); + assertThat(parsed).isInstanceOf(ParseError.class); + assertThat(parsed.printAll()).isEqualTo(policy); + // "AAA," previously came back as "AAA=" from an '=' that error recovery invented. + assertThat(parseFailure(parsed)).doesNotContain("AAA="); + } + + @Issue("https://github.com/openrewrite/rewrite/pull/7906") + @Test + void nestedAttributeValueWithUnescapedQuoteAndAngleBracketDoesNotThrow() { + // Same input one level of nesting deeper, which previously reached visitAttribute with a null EQUALS + // token and threw a NullPointerException instead of falling back to a ParseError. + SourceFile parsed = XmlParser.builder().build() + .parse(new InMemoryExecutionContext(t -> { + }), "") + .findFirst().orElseThrow(); + assertThat(parsed).isInstanceOf(ParseError.class); + assertThat(parsed.printAll()).isEqualTo(""); + assertThat(parseFailure(parsed)).doesNotContain("NullPointerException"); + } + + private static String parseFailure(SourceFile parsed) { + return parsed.getMarkers().findFirst(ParseExceptionResult.class) + .orElseThrow().getMessage(); + } }