From ea033714b47e3d8088a5f6135343743df0369d61 Mon Sep 17 00:00:00 2001 From: aboyko Date: Fri, 1 Nov 2024 18:49:15 -0400 Subject: [PATCH] Embedded code accounts for concatenated strings and escape chars --- .../semantic/tokens/SemanticTokenData.java | 28 +- .../tokens/SemanticTokensDataProvider.java | 2 +- .../semantic/tokens/SemanticTokensUtils.java | 12 +- .../ide/vscode/commons/util/text/IRegion.java | 6 + .../commons/jpql/grammars/PostgreSqlLexer.g4 | 3 +- .../parser/postgresql/PostgreSqlLexer.java | 2316 ++++++++--------- .../ide/vscode/boot/app/SpringDataConfig.java | 2 +- .../vscode/boot/java/cron/CronReconciler.java | 17 +- .../boot/java/cron/CronSemanticTokens.java | 6 +- .../boot/java/cron/JdtCronReconciler.java | 6 +- .../cron/JdtCronSemanticTokensProvider.java | 9 +- .../boot/java/cron/JdtCronVisitorUtils.java | 9 +- .../DataQueryParameterDefinitionProvider.java | 6 +- .../data/jpa/queries/HqlSemanticTokens.java | 11 +- .../JdtDataQueriesInlayHintsProvider.java | 8 +- .../JdtDataQuerySemanticTokensProvider.java | 18 +- .../JdtQueryDocHighlightsProvider.java | 4 +- .../jpa/queries/JdtQueryVisitorUtils.java | 31 +- .../data/jpa/queries/JpqlSemanticTokens.java | 21 +- .../data/jpa/queries/MySqlSemanticTokens.java | 17 +- .../NamedQueryPropertiesReconcileEngine.java | 3 +- .../jpa/queries/PostgreSqlSemanticTokens.java | 9 +- .../jpa/queries/QueryJdtAstReconciler.java | 44 +- .../QueryPropertiesSemanticTokensHandler.java | 5 +- .../lang}/AntlrReconciler.java | 14 +- .../lang}/AntlrReconcilerWithSpel.java | 16 +- .../queries => embadded/lang}/AntlrUtils.java | 2 +- .../CompositeEmbeddedLanguageSnippet.java | 92 + .../embadded/lang/EmbeddedLangAstUtils.java | 57 + .../lang/EmbeddedLanguageSnippet.java | 37 + ...dedLanguageSnippetWithPrefixAndSuffix.java | 45 + .../lang/StringLiteralLanguageSnippet.java | 100 + .../lang/TextBlockLanguageSnippet.java | 96 + .../handlers/CopilotCodeLensProvider.java | 18 +- .../vscode/boot/java/handlers/Reconciler.java | 5 +- .../handlers/SpelExpressionReconciler.java | 18 +- .../spel/AnnotationParamSpelExtractor.java | 33 +- .../boot/java/spel/JdtSpelReconciler.java | 4 +- .../spel/JdtSpelSemanticTokensProvider.java | 10 +- .../PropertyPlaceHolderSemanticTokens.java | 12 +- .../java/spel/SpelDefinitionProvider.java | 27 +- .../vscode/boot/java/spel/SpelReconciler.java | 20 +- .../boot/java/spel/SpelSemanticTokens.java | 81 +- .../vscode/boot/xml/XMLElementReconciler.java | 3 +- .../boot/java/cron/CronReconcilerTest.java | 13 +- .../java/cron/CronSemanticTokensTest.java | 36 +- .../JdtCronSemanticTokensProviderTest.java | 90 +- .../jpa/queries/HqlSemanticTokensTest.java | 26 +- ...dtDataQuerySemanticTokensProviderTest.java | 179 +- .../jpa/queries/JpqlSemanticTokensTest.java | 22 +- .../jpa/queries/MySqlSemanticTokensTest.java | 8 +- .../queries/PostgreSqlSemanticTokensTest.java | 55 +- .../JdtSpelSemanticTokensProviderTest.java | 123 +- ...PropertyPlaceHolderSemanticTokensTest.java | 10 +- .../java/spel/SpelSemanticTokensTest.java | 22 +- 55 files changed, 2272 insertions(+), 1595 deletions(-) rename headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/{data/jpa/queries => embadded/lang}/AntlrReconciler.java (87%) rename headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/{data/jpa/queries => embadded/lang}/AntlrReconcilerWithSpel.java (74%) rename headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/{data/jpa/queries => embadded/lang}/AntlrUtils.java (94%) create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/CompositeEmbeddedLanguageSnippet.java create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLangAstUtils.java create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLanguageSnippet.java create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLanguageSnippetWithPrefixAndSuffix.java create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/StringLiteralLanguageSnippet.java create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/TextBlockLanguageSnippet.java diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokenData.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokenData.java index 834745dec..dd46bc8da 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokenData.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokenData.java @@ -13,19 +13,25 @@ package org.springframework.ide.vscode.commons.languageserver.semantic.tokens; import java.util.Arrays; import java.util.Objects; +import org.springframework.ide.vscode.commons.util.text.IRegion; +import org.springframework.ide.vscode.commons.util.text.Region; + public record SemanticTokenData( - int start, - int end, + IRegion range, String type, String[] modifiers ) implements Comparable { + + public SemanticTokenData(int start, int end, String type, String[] modifiers) { + this(new Region(start, end -start), type, modifiers); + } @Override public int compareTo(SemanticTokenData o) { - if (start == o.start) { - return end - o.end; + if (range.getOffset() == o.range().getOffset()) { + return range.getLength() - o.range().getLength(); } - return start - o.start; + return range.getOffset() - o.range().getOffset(); } @Override @@ -33,7 +39,7 @@ public record SemanticTokenData( final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(modifiers); - result = prime * result + Objects.hash(end, start, type); + result = prime * result + Objects.hash(range, type); return result; } @@ -46,8 +52,16 @@ public record SemanticTokenData( if (getClass() != obj.getClass()) return false; SemanticTokenData other = (SemanticTokenData) obj; - return end == other.end && Arrays.equals(modifiers, other.modifiers) && start == other.start + return range.getLength() == other.range.getLength() && Arrays.equals(modifiers, other.modifiers) && range.getOffset() == other.range().getOffset() && Objects.equals(type, other.type); } + public int getStart() { + return range.getStart(); + } + + public int getEnd() { + return range.getEnd(); + } + } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokensDataProvider.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokensDataProvider.java index 9e45594ef..d52ad8ad3 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokensDataProvider.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokensDataProvider.java @@ -17,6 +17,6 @@ public interface SemanticTokensDataProvider { List getTokenTypes(); default List getTypeModifiers() { return Collections.emptyList(); } - List computeTokens(String text, int initialOffset); + List computeTokens(String text); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokensUtils.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokensUtils.java index ac52dcbb8..f77feb46a 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokensUtils.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/semantic/tokens/SemanticTokensUtils.java @@ -52,11 +52,11 @@ public class SemanticTokensUtils { int previousLine = 0; int previousColumn = 0; for (SemanticTokenData tokenData : tokensData) { - int currentLine = getLineNumber.apply(tokenData.start()); - int currentColumn = getColumnNumber.apply(tokenData.start()); + int currentLine = getLineNumber.apply(tokenData.getStart()); + int currentColumn = getColumnNumber.apply(tokenData.getStart()); data.add(currentLine - previousLine); data.add(currentLine == previousLine ? currentColumn - previousColumn : currentColumn); - data.add(tokenData.end() - tokenData.start()); + data.add(tokenData.getEnd() - tokenData.getStart()); data.add(SemanticTokensUtils.getSemanticTokenTypeIndex(legend, tokenData.type())); data.add(SemanticTokensUtils.getSemanticTokenModifiersFlags(legend, tokenData.modifiers())); previousLine = currentLine; @@ -79,11 +79,11 @@ public class SemanticTokensUtils { int previousColumn = 0; for (SemanticTokenData tokenData : tokensData) { try { - int currentLine = doc.getLineOfOffset(tokenData.start()); - int currentColumn = tokenData.start() - doc.getLineOffset(currentLine); + int currentLine = doc.getLineOfOffset(tokenData.getStart()); + int currentColumn = tokenData.getStart() - doc.getLineOffset(currentLine); data.add(currentLine - previousLine); data.add(currentLine == previousLine ? currentColumn - previousColumn : currentColumn); - data.add(tokenData.end() - tokenData.start()); + data.add(tokenData.getEnd() - tokenData.getStart()); data.add(SemanticTokensUtils.getSemanticTokenTypeIndex(legend, tokenData.type())); data.add(SemanticTokensUtils.getSemanticTokenModifiersFlags(legend, tokenData.modifiers())); previousLine = currentLine; diff --git a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/IRegion.java b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/IRegion.java index 0fab5de7e..63141e728 100644 --- a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/IRegion.java +++ b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/IRegion.java @@ -18,5 +18,11 @@ public interface IRegion { int getOffset(); int getLength(); + default int getEnd() { + return getOffset() + getLength(); + } + default int getStart() { + return getOffset(); + } } diff --git a/headless-services/commons/jpql/grammars/PostgreSqlLexer.g4 b/headless-services/commons/jpql/grammars/PostgreSqlLexer.g4 index 2b7484726..6b4dc828a 100644 --- a/headless-services/commons/jpql/grammars/PostgreSqlLexer.g4 +++ b/headless-services/commons/jpql/grammars/PostgreSqlLexer.g4 @@ -1489,7 +1489,7 @@ InvalidUnterminatedUnicodeQuotedIdentifier: 'U' '&' InvalidUnterminatedQuotedIde StringConstant: UnterminatedStringConstant '\''; -UnterminatedStringConstant: '\'' ('\'\'' | ~ '\'' | '\\\\\'' | '\\\'')*; +UnterminatedStringConstant: '\'' ('\'\'' | ~ '\'' | '\\\'')*; // String Constants with C-style Escapes (4.1.2.2) BeginEscapeStringConstant: 'E' '\'' -> more, pushMode (EscapeStringConstantMode); @@ -1625,7 +1625,6 @@ fragment EscapeStringText options { }: ( '\\\'' - | '\'\'\'' | '\\' ( // two-digit hex escapes are still valid when treated as single-digit escapes 'x' [0-9a-fA-F] diff --git a/headless-services/commons/jpql/src/main/java/org/springframework/ide/vscode/parser/postgresql/PostgreSqlLexer.java b/headless-services/commons/jpql/src/main/java/org/springframework/ide/vscode/parser/postgresql/PostgreSqlLexer.java index 5562c0de3..d599d2d64 100644 --- a/headless-services/commons/jpql/src/main/java/org/springframework/ide/vscode/parser/postgresql/PostgreSqlLexer.java +++ b/headless-services/commons/jpql/src/main/java/org/springframework/ide/vscode/parser/postgresql/PostgreSqlLexer.java @@ -679,7 +679,7 @@ public class PostgreSqlLexer extends PostgreSqlLexerBase { } private static final String _serializedATNSegment0 = - "\u0004\u0000\u02a7\u1aa2\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+ + "\u0004\u0000\u02a7\u1a9c\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+ "\uffff\u0006\uffff\uffff\u0006\uffff\uffff\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"+ @@ -1691,75 +1691,74 @@ public class PostgreSqlLexer extends PostgreSqlLexerBase { "\u0001\u028c\u0001\u028c\u0001\u028c\u0001\u028c\u0001\u028d\u0001\u028d"+ "\u0001\u028d\u0001\u028d\u0001\u028e\u0001\u028e\u0001\u028e\u0001\u028e"+ "\u0001\u028f\u0001\u028f\u0001\u028f\u0001\u0290\u0001\u0290\u0001\u0290"+ - "\u0001\u0290\u0001\u0290\u0001\u0290\u0001\u0290\u0001\u0290\u0001\u0290"+ - "\u0005\u0290\u1921\b\u0290\n\u0290\f\u0290\u1924\t\u0290\u0001\u0291\u0001"+ - "\u0291\u0001\u0291\u0001\u0291\u0001\u0291\u0001\u0291\u0001\u0292\u0001"+ - "\u0292\u0001\u0292\u0001\u0293\u0001\u0293\u0001\u0293\u0001\u0293\u0001"+ - "\u0294\u0001\u0294\u0003\u0294\u1935\b\u0294\u0001\u0294\u0001\u0294\u0001"+ - "\u0294\u0001\u0294\u0001\u0294\u0001\u0295\u0001\u0295\u0005\u0295\u193e"+ - "\b\u0295\n\u0295\f\u0295\u1941\t\u0295\u0001\u0296\u0001\u0296\u0001\u0296"+ - "\u0001\u0297\u0001\u0297\u0001\u0297\u0005\u0297\u1949\b\u0297\n\u0297"+ - "\f\u0297\u194c\t\u0297\u0001\u0298\u0001\u0298\u0001\u0298\u0001\u0299"+ - "\u0001\u0299\u0001\u0299\u0001\u029a\u0001\u029a\u0001\u029a\u0001\u029b"+ - "\u0001\u029b\u0001\u029b\u0005\u029b\u195a\b\u029b\n\u029b\f\u029b\u195d"+ - "\t\u029b\u0001\u029c\u0001\u029c\u0001\u029c\u0001\u029d\u0001\u029d\u0001"+ - "\u029d\u0001\u029e\u0001\u029e\u0001\u029f\u0001\u029f\u0001\u029f\u0001"+ - "\u029f\u0001\u029f\u0001\u029f\u0001\u02a0\u0001\u02a0\u0001\u02a0\u0003"+ - "\u02a0\u1970\b\u02a0\u0001\u02a0\u0001\u02a0\u0003\u02a0\u1974\b\u02a0"+ - "\u0001\u02a0\u0003\u02a0\u1977\b\u02a0\u0001\u02a0\u0001\u02a0\u0001\u02a0"+ - "\u0001\u02a0\u0003\u02a0\u197d\b\u02a0\u0001\u02a0\u0003\u02a0\u1980\b"+ - "\u02a0\u0001\u02a0\u0001\u02a0\u0001\u02a0\u0003\u02a0\u1985\b\u02a0\u0001"+ - "\u02a0\u0001\u02a0\u0003\u02a0\u1989\b\u02a0\u0001\u02a1\u0004\u02a1\u198c"+ - "\b\u02a1\u000b\u02a1\f\u02a1\u198d\u0001\u02a2\u0001\u02a2\u0001\u02a2"+ - "\u0001\u02a2\u0001\u02a2\u0001\u02a2\u0001\u02a2\u0001\u02a2\u0005\u02a2"+ - "\u1998\b\u02a2\n\u02a2\f\u02a2\u199b\t\u02a2\u0001\u02a2\u0001\u02a2\u0001"+ - "\u02a3\u0004\u02a3\u19a0\b\u02a3\u000b\u02a3\f\u02a3\u19a1\u0001\u02a3"+ - "\u0001\u02a3\u0001\u02a4\u0001\u02a4\u0003\u02a4\u19a8\b\u02a4\u0001\u02a4"+ - "\u0003\u02a4\u19ab\b\u02a4\u0001\u02a4\u0001\u02a4\u0001\u02a5\u0001\u02a5"+ - "\u0001\u02a5\u0001\u02a5\u0005\u02a5\u19b3\b\u02a5\n\u02a5\f\u02a5\u19b6"+ - "\t\u02a5\u0001\u02a5\u0001\u02a5\u0001\u02a6\u0001\u02a6\u0001\u02a6\u0001"+ - "\u02a6\u0005\u02a6\u19be\b\u02a6\n\u02a6\f\u02a6\u19c1\t\u02a6\u0001\u02a6"+ - "\u0001\u02a6\u0001\u02a6\u0004\u02a6\u19c6\b\u02a6\u000b\u02a6\f\u02a6"+ - "\u19c7\u0001\u02a6\u0001\u02a6\u0004\u02a6\u19cc\b\u02a6\u000b\u02a6\f"+ - "\u02a6\u19cd\u0001\u02a6\u0005\u02a6\u19d1\b\u02a6\n\u02a6\f\u02a6\u19d4"+ - "\t\u02a6\u0001\u02a6\u0005\u02a6\u19d7\b\u02a6\n\u02a6\f\u02a6\u19da\t"+ - "\u02a6\u0001\u02a6\u0001\u02a6\u0001\u02a6\u0001\u02a6\u0001\u02a6\u0001"+ - "\u02a7\u0001\u02a7\u0001\u02a7\u0001\u02a7\u0005\u02a7\u19e5\b\u02a7\n"+ - "\u02a7\f\u02a7\u19e8\t\u02a7\u0001\u02a7\u0001\u02a7\u0001\u02a7\u0004"+ - "\u02a7\u19ed\b\u02a7\u000b\u02a7\f\u02a7\u19ee\u0001\u02a7\u0001\u02a7"+ - "\u0004\u02a7\u19f3\b\u02a7\u000b\u02a7\f\u02a7\u19f4\u0001\u02a7\u0003"+ - "\u02a7\u19f8\b\u02a7\u0005\u02a7\u19fa\b\u02a7\n\u02a7\f\u02a7\u19fd\t"+ - "\u02a7\u0001\u02a7\u0004\u02a7\u1a00\b\u02a7\u000b\u02a7\f\u02a7\u1a01"+ - "\u0001\u02a7\u0004\u02a7\u1a05\b\u02a7\u000b\u02a7\f\u02a7\u1a06\u0001"+ - "\u02a7\u0005\u02a7\u1a0a\b\u02a7\n\u02a7\f\u02a7\u1a0d\t\u02a7\u0001\u02a7"+ - "\u0003\u02a7\u1a10\b\u02a7\u0001\u02a7\u0001\u02a7\u0001\u02a8\u0001\u02a8"+ - "\u0001\u02a8\u0001\u02a8\u0005\u02a8\u1a18\b\u02a8\n\u02a8\f\u02a8\u1a1b"+ - "\t\u02a8\u0001\u02a8\u0005\u02a8\u1a1e\b\u02a8\n\u02a8\f\u02a8\u1a21\t"+ - "\u02a8\u0001\u02a8\u0001\u02a8\u0005\u02a8\u1a25\b\u02a8\n\u02a8\f\u02a8"+ - "\u1a28\t\u02a8\u0003\u02a8\u1a2a\b\u02a8\u0001\u02a9\u0001\u02a9\u0001"+ - "\u02a9\u0001\u02aa\u0001\u02aa\u0001\u02ab\u0001\u02ab\u0001\u02ab\u0001"+ - "\u02ab\u0001\u02ab\u0001\u02ac\u0001\u02ac\u0003\u02ac\u1a38\b\u02ac\u0001"+ - "\u02ac\u0001\u02ac\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001"+ - "\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001"+ - "\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001"+ - "\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001"+ - "\u02ad\u0003\u02ad\u1a53\b\u02ad\u0001\u02ad\u0005\u02ad\u1a56\b\u02ad"+ - "\n\u02ad\f\u02ad\u1a59\t\u02ad\u0001\u02ae\u0001\u02ae\u0001\u02ae\u0001"+ - "\u02ae\u0001\u02ae\u0001\u02af\u0001\u02af\u0003\u02af\u1a62\b\u02af\u0001"+ - "\u02af\u0001\u02af\u0001\u02b0\u0001\u02b0\u0001\u02b0\u0001\u02b0\u0001"+ - "\u02b0\u0005\u02b0\u1a6b\b\u02b0\n\u02b0\f\u02b0\u1a6e\t\u02b0\u0001\u02b1"+ - "\u0001\u02b1\u0001\u02b1\u0001\u02b1\u0001\u02b1\u0001\u02b2\u0001\u02b2"+ - "\u0001\u02b2\u0001\u02b2\u0001\u02b2\u0001\u02b2\u0001\u02b3\u0001\u02b3"+ - "\u0001\u02b3\u0001\u02b3\u0001\u02b3\u0001\u02b4\u0001\u02b4\u0001\u02b4"+ - "\u0001\u02b4\u0001\u02b4\u0001\u02b5\u0001\u02b5\u0001\u02b5\u0001\u02b5"+ - "\u0001\u02b5\u0001\u02b6\u0004\u02b6\u1a8b\b\u02b6\u000b\u02b6\f\u02b6"+ - "\u1a8c\u0001\u02b6\u0001\u02b6\u0005\u02b6\u1a91\b\u02b6\n\u02b6\f\u02b6"+ - "\u1a94\t\u02b6\u0003\u02b6\u1a96\b\u02b6\u0001\u02b7\u0001\u02b7\u0003"+ - "\u02b7\u1a9a\b\u02b7\u0001\u02b7\u0001\u02b7\u0001\u02b7\u0001\u02b7\u0001"+ - "\u02b7\u0001\u02b7\u0001\u02b7\u0001\u057e\u0000\u02b8\u0005\u0001\u0007"+ - "\u0000\t\u0002\u000b\u0003\r\u0004\u000f\u0005\u0011\u0006\u0013\u0007"+ - "\u0015\b\u0017\t\u0019\n\u001b\u000b\u001d\f\u001f\r!\u000e#\u000f%\u0010"+ - "\'\u0011)\u0012+\u0013-\u0014/\u00151\u00163\u00175\u00187\u00199\u001a"+ + "\u0001\u0290\u0001\u0290\u0001\u0290\u0005\u0290\u191e\b\u0290\n\u0290"+ + "\f\u0290\u1921\t\u0290\u0001\u0291\u0001\u0291\u0001\u0291\u0001\u0291"+ + "\u0001\u0291\u0001\u0291\u0001\u0292\u0001\u0292\u0001\u0292\u0001\u0293"+ + "\u0001\u0293\u0001\u0293\u0001\u0293\u0001\u0294\u0001\u0294\u0003\u0294"+ + "\u1932\b\u0294\u0001\u0294\u0001\u0294\u0001\u0294\u0001\u0294\u0001\u0294"+ + "\u0001\u0295\u0001\u0295\u0005\u0295\u193b\b\u0295\n\u0295\f\u0295\u193e"+ + "\t\u0295\u0001\u0296\u0001\u0296\u0001\u0296\u0001\u0297\u0001\u0297\u0001"+ + "\u0297\u0005\u0297\u1946\b\u0297\n\u0297\f\u0297\u1949\t\u0297\u0001\u0298"+ + "\u0001\u0298\u0001\u0298\u0001\u0299\u0001\u0299\u0001\u0299\u0001\u029a"+ + "\u0001\u029a\u0001\u029a\u0001\u029b\u0001\u029b\u0001\u029b\u0005\u029b"+ + "\u1957\b\u029b\n\u029b\f\u029b\u195a\t\u029b\u0001\u029c\u0001\u029c\u0001"+ + "\u029c\u0001\u029d\u0001\u029d\u0001\u029d\u0001\u029e\u0001\u029e\u0001"+ + "\u029f\u0001\u029f\u0001\u029f\u0001\u029f\u0001\u029f\u0001\u029f\u0001"+ + "\u02a0\u0001\u02a0\u0001\u02a0\u0003\u02a0\u196d\b\u02a0\u0001\u02a0\u0001"+ + "\u02a0\u0003\u02a0\u1971\b\u02a0\u0001\u02a0\u0003\u02a0\u1974\b\u02a0"+ + "\u0001\u02a0\u0001\u02a0\u0001\u02a0\u0001\u02a0\u0003\u02a0\u197a\b\u02a0"+ + "\u0001\u02a0\u0003\u02a0\u197d\b\u02a0\u0001\u02a0\u0001\u02a0\u0001\u02a0"+ + "\u0003\u02a0\u1982\b\u02a0\u0001\u02a0\u0001\u02a0\u0003\u02a0\u1986\b"+ + "\u02a0\u0001\u02a1\u0004\u02a1\u1989\b\u02a1\u000b\u02a1\f\u02a1\u198a"+ + "\u0001\u02a2\u0001\u02a2\u0001\u02a2\u0001\u02a2\u0001\u02a2\u0001\u02a2"+ + "\u0001\u02a2\u0001\u02a2\u0005\u02a2\u1995\b\u02a2\n\u02a2\f\u02a2\u1998"+ + "\t\u02a2\u0001\u02a2\u0001\u02a2\u0001\u02a3\u0004\u02a3\u199d\b\u02a3"+ + "\u000b\u02a3\f\u02a3\u199e\u0001\u02a3\u0001\u02a3\u0001\u02a4\u0001\u02a4"+ + "\u0003\u02a4\u19a5\b\u02a4\u0001\u02a4\u0003\u02a4\u19a8\b\u02a4\u0001"+ + "\u02a4\u0001\u02a4\u0001\u02a5\u0001\u02a5\u0001\u02a5\u0001\u02a5\u0005"+ + "\u02a5\u19b0\b\u02a5\n\u02a5\f\u02a5\u19b3\t\u02a5\u0001\u02a5\u0001\u02a5"+ + "\u0001\u02a6\u0001\u02a6\u0001\u02a6\u0001\u02a6\u0005\u02a6\u19bb\b\u02a6"+ + "\n\u02a6\f\u02a6\u19be\t\u02a6\u0001\u02a6\u0001\u02a6\u0001\u02a6\u0004"+ + "\u02a6\u19c3\b\u02a6\u000b\u02a6\f\u02a6\u19c4\u0001\u02a6\u0001\u02a6"+ + "\u0004\u02a6\u19c9\b\u02a6\u000b\u02a6\f\u02a6\u19ca\u0001\u02a6\u0005"+ + "\u02a6\u19ce\b\u02a6\n\u02a6\f\u02a6\u19d1\t\u02a6\u0001\u02a6\u0005\u02a6"+ + "\u19d4\b\u02a6\n\u02a6\f\u02a6\u19d7\t\u02a6\u0001\u02a6\u0001\u02a6\u0001"+ + "\u02a6\u0001\u02a6\u0001\u02a6\u0001\u02a7\u0001\u02a7\u0001\u02a7\u0001"+ + "\u02a7\u0005\u02a7\u19e2\b\u02a7\n\u02a7\f\u02a7\u19e5\t\u02a7\u0001\u02a7"+ + "\u0001\u02a7\u0001\u02a7\u0004\u02a7\u19ea\b\u02a7\u000b\u02a7\f\u02a7"+ + "\u19eb\u0001\u02a7\u0001\u02a7\u0004\u02a7\u19f0\b\u02a7\u000b\u02a7\f"+ + "\u02a7\u19f1\u0001\u02a7\u0003\u02a7\u19f5\b\u02a7\u0005\u02a7\u19f7\b"+ + "\u02a7\n\u02a7\f\u02a7\u19fa\t\u02a7\u0001\u02a7\u0004\u02a7\u19fd\b\u02a7"+ + "\u000b\u02a7\f\u02a7\u19fe\u0001\u02a7\u0004\u02a7\u1a02\b\u02a7\u000b"+ + "\u02a7\f\u02a7\u1a03\u0001\u02a7\u0005\u02a7\u1a07\b\u02a7\n\u02a7\f\u02a7"+ + "\u1a0a\t\u02a7\u0001\u02a7\u0003\u02a7\u1a0d\b\u02a7\u0001\u02a7\u0001"+ + "\u02a7\u0001\u02a8\u0001\u02a8\u0001\u02a8\u0001\u02a8\u0005\u02a8\u1a15"+ + "\b\u02a8\n\u02a8\f\u02a8\u1a18\t\u02a8\u0001\u02a8\u0005\u02a8\u1a1b\b"+ + "\u02a8\n\u02a8\f\u02a8\u1a1e\t\u02a8\u0001\u02a8\u0001\u02a8\u0005\u02a8"+ + "\u1a22\b\u02a8\n\u02a8\f\u02a8\u1a25\t\u02a8\u0003\u02a8\u1a27\b\u02a8"+ + "\u0001\u02a9\u0001\u02a9\u0001\u02a9\u0001\u02aa\u0001\u02aa\u0001\u02ab"+ + "\u0001\u02ab\u0001\u02ab\u0001\u02ab\u0001\u02ab\u0001\u02ac\u0001\u02ac"+ + "\u0003\u02ac\u1a35\b\u02ac\u0001\u02ac\u0001\u02ac\u0001\u02ad\u0001\u02ad"+ + "\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad"+ + "\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad"+ + "\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad\u0001\u02ad"+ + "\u0003\u02ad\u1a4d\b\u02ad\u0001\u02ad\u0005\u02ad\u1a50\b\u02ad\n\u02ad"+ + "\f\u02ad\u1a53\t\u02ad\u0001\u02ae\u0001\u02ae\u0001\u02ae\u0001\u02ae"+ + "\u0001\u02ae\u0001\u02af\u0001\u02af\u0003\u02af\u1a5c\b\u02af\u0001\u02af"+ + "\u0001\u02af\u0001\u02b0\u0001\u02b0\u0001\u02b0\u0001\u02b0\u0001\u02b0"+ + "\u0005\u02b0\u1a65\b\u02b0\n\u02b0\f\u02b0\u1a68\t\u02b0\u0001\u02b1\u0001"+ + "\u02b1\u0001\u02b1\u0001\u02b1\u0001\u02b1\u0001\u02b2\u0001\u02b2\u0001"+ + "\u02b2\u0001\u02b2\u0001\u02b2\u0001\u02b2\u0001\u02b3\u0001\u02b3\u0001"+ + "\u02b3\u0001\u02b3\u0001\u02b3\u0001\u02b4\u0001\u02b4\u0001\u02b4\u0001"+ + "\u02b4\u0001\u02b4\u0001\u02b5\u0001\u02b5\u0001\u02b5\u0001\u02b5\u0001"+ + "\u02b5\u0001\u02b6\u0004\u02b6\u1a85\b\u02b6\u000b\u02b6\f\u02b6\u1a86"+ + "\u0001\u02b6\u0001\u02b6\u0005\u02b6\u1a8b\b\u02b6\n\u02b6\f\u02b6\u1a8e"+ + "\t\u02b6\u0003\u02b6\u1a90\b\u02b6\u0001\u02b7\u0001\u02b7\u0003\u02b7"+ + "\u1a94\b\u02b7\u0001\u02b7\u0001\u02b7\u0001\u02b7\u0001\u02b7\u0001\u02b7"+ + "\u0001\u02b7\u0001\u02b7\u0001\u057e\u0000\u02b8\u0005\u0001\u0007\u0000"+ + "\t\u0002\u000b\u0003\r\u0004\u000f\u0005\u0011\u0006\u0013\u0007\u0015"+ + "\b\u0017\t\u0019\n\u001b\u000b\u001d\f\u001f\r!\u000e#\u000f%\u0010\'"+ + "\u0011)\u0012+\u0013-\u0014/\u00151\u00163\u00175\u00187\u00199\u001a"+ ";\u001b=\u001c?\u001dA\u001eC\u001fE\u0000G\u0000I\u0000K\u0000M O!Q\""+ "S#U$W%Y&[\'](_)a*c+e,g-i.k/m0o1q2s3u4w5y6{7}8\u007f9\u0081:\u0083;\u0085"+ "<\u0087=\u0089>\u008b?\u008d@\u008fA\u0091B\u0093C\u0095D\u0097E\u0099"+ @@ -1877,7 +1876,7 @@ public class PostgreSqlLexer extends PostgreSqlLexerBase { "\"\"\u0001\u0000\'\'\u0001\u000001\u0003\u000009AFaf\u0002\u0000\"\"\\"+ "\\\u0002\u0000\t\t \u0002\u0000\n\n\r\r\u0002\u0000**//\u0004\u0000\n"+ "\n\r\r\"\"\\\\\u0003\u0000\n\n\r\r\"\"\u0003\u0000UUuuxx\u0002\u0000\'"+ - "\'\\\\\u0001\u0000$$\u1af2\u0000\u0005\u0001\u0000\u0000\u0000\u0000\t"+ + "\'\\\\\u0001\u0000$$\u1aea\u0000\u0005\u0001\u0000\u0000\u0000\u0000\t"+ "\u0001\u0000\u0000\u0000\u0000\u000b\u0001\u0000\u0000\u0000\u0000\r\u0001"+ "\u0000\u0000\u0000\u0000\u000f\u0001\u0000\u0000\u0000\u0000\u0011\u0001"+ "\u0000\u0000\u0000\u0000\u0013\u0001\u0000\u0000\u0000\u0000\u0015\u0001"+ @@ -2400,9 +2399,9 @@ public class PostgreSqlLexer extends PostgreSqlLexerBase { "\u0000\u0000\u02e5\u0fe4\u0001\u0000\u0000\u0000\u02e7\u0feb\u0001\u0000"+ "\u0000\u0000\u02e9\u0ff2\u0001\u0000\u0000\u0000\u02eb\u0ff8\u0001\u0000"+ "\u0000\u0000\u02ed\u1001\u0001\u0000\u0000\u0000\u02ef\u100b\u0001\u0000"+ - "\u0000\u0000\u02f1\u1013\u0001\u0000\u0000\u0000"; + "\u0000\u0000\u02f1\u1013\u0001\u0000\u0000\u0000\u02f3\u101b\u0001\u0000"+ + "\u0000\u0000\u02f5\u1020\u0001\u0000\u0000\u0000"; private static final String _serializedATNSegment1 = - "\u02f3\u101b\u0001\u0000\u0000\u0000\u02f5\u1020\u0001\u0000\u0000\u0000"+ "\u02f7\u1029\u0001\u0000\u0000\u0000\u02f9\u1034\u0001\u0000\u0000\u0000"+ "\u02fb\u103c\u0001\u0000\u0000\u0000\u02fd\u1041\u0001\u0000\u0000\u0000"+ "\u02ff\u1049\u0001\u0000\u0000\u0000\u0301\u104f\u0001\u0000\u0000\u0000"+ @@ -2543,26 +2542,26 @@ public class PostgreSqlLexer extends PostgreSqlLexerBase { "\u051b\u1904\u0001\u0000\u0000\u0000\u051d\u1908\u0001\u0000\u0000\u0000"+ "\u051f\u190c\u0001\u0000\u0000\u0000\u0521\u1910\u0001\u0000\u0000\u0000"+ "\u0523\u1914\u0001\u0000\u0000\u0000\u0525\u1917\u0001\u0000\u0000\u0000"+ - "\u0527\u1925\u0001\u0000\u0000\u0000\u0529\u192b\u0001\u0000\u0000\u0000"+ - "\u052b\u192e\u0001\u0000\u0000\u0000\u052d\u1932\u0001\u0000\u0000\u0000"+ - "\u052f\u193b\u0001\u0000\u0000\u0000\u0531\u1942\u0001\u0000\u0000\u0000"+ - "\u0533\u1945\u0001\u0000\u0000\u0000\u0535\u194d\u0001\u0000\u0000\u0000"+ - "\u0537\u1950\u0001\u0000\u0000\u0000\u0539\u1953\u0001\u0000\u0000\u0000"+ - "\u053b\u1956\u0001\u0000\u0000\u0000\u053d\u195e\u0001\u0000\u0000\u0000"+ - "\u053f\u1961\u0001\u0000\u0000\u0000\u0541\u1964\u0001\u0000\u0000\u0000"+ - "\u0543\u1966\u0001\u0000\u0000\u0000\u0545\u1988\u0001\u0000\u0000\u0000"+ - "\u0547\u198b\u0001\u0000\u0000\u0000\u0549\u198f\u0001\u0000\u0000\u0000"+ - "\u054b\u199f\u0001\u0000\u0000\u0000\u054d\u19aa\u0001\u0000\u0000\u0000"+ - "\u054f\u19ae\u0001\u0000\u0000\u0000\u0551\u19b9\u0001\u0000\u0000\u0000"+ - "\u0553\u19e0\u0001\u0000\u0000\u0000\u0555\u1a13\u0001\u0000\u0000\u0000"+ - "\u0557\u1a2b\u0001\u0000\u0000\u0000\u0559\u1a2e\u0001\u0000\u0000\u0000"+ - "\u055b\u1a30\u0001\u0000\u0000\u0000\u055d\u1a35\u0001\u0000\u0000\u0000"+ - "\u055f\u1a57\u0001\u0000\u0000\u0000\u0561\u1a5a\u0001\u0000\u0000\u0000"+ - "\u0563\u1a5f\u0001\u0000\u0000\u0000\u0565\u1a6c\u0001\u0000\u0000\u0000"+ - "\u0567\u1a6f\u0001\u0000\u0000\u0000\u0569\u1a74\u0001\u0000\u0000\u0000"+ - "\u056b\u1a7a\u0001\u0000\u0000\u0000\u056d\u1a7f\u0001\u0000\u0000\u0000"+ - "\u056f\u1a84\u0001\u0000\u0000\u0000\u0571\u1a95\u0001\u0000\u0000\u0000"+ - "\u0573\u1a97\u0001\u0000\u0000\u0000\u0575\u0576\u0005#\u0000\u0000\u0576"+ + "\u0527\u1922\u0001\u0000\u0000\u0000\u0529\u1928\u0001\u0000\u0000\u0000"+ + "\u052b\u192b\u0001\u0000\u0000\u0000\u052d\u192f\u0001\u0000\u0000\u0000"+ + "\u052f\u1938\u0001\u0000\u0000\u0000\u0531\u193f\u0001\u0000\u0000\u0000"+ + "\u0533\u1942\u0001\u0000\u0000\u0000\u0535\u194a\u0001\u0000\u0000\u0000"+ + "\u0537\u194d\u0001\u0000\u0000\u0000\u0539\u1950\u0001\u0000\u0000\u0000"+ + "\u053b\u1953\u0001\u0000\u0000\u0000\u053d\u195b\u0001\u0000\u0000\u0000"+ + "\u053f\u195e\u0001\u0000\u0000\u0000\u0541\u1961\u0001\u0000\u0000\u0000"+ + "\u0543\u1963\u0001\u0000\u0000\u0000\u0545\u1985\u0001\u0000\u0000\u0000"+ + "\u0547\u1988\u0001\u0000\u0000\u0000\u0549\u198c\u0001\u0000\u0000\u0000"+ + "\u054b\u199c\u0001\u0000\u0000\u0000\u054d\u19a7\u0001\u0000\u0000\u0000"+ + "\u054f\u19ab\u0001\u0000\u0000\u0000\u0551\u19b6\u0001\u0000\u0000\u0000"+ + "\u0553\u19dd\u0001\u0000\u0000\u0000\u0555\u1a10\u0001\u0000\u0000\u0000"+ + "\u0557\u1a28\u0001\u0000\u0000\u0000\u0559\u1a2b\u0001\u0000\u0000\u0000"+ + "\u055b\u1a2d\u0001\u0000\u0000\u0000\u055d\u1a32\u0001\u0000\u0000\u0000"+ + "\u055f\u1a51\u0001\u0000\u0000\u0000\u0561\u1a54\u0001\u0000\u0000\u0000"+ + "\u0563\u1a59\u0001\u0000\u0000\u0000\u0565\u1a66\u0001\u0000\u0000\u0000"+ + "\u0567\u1a69\u0001\u0000\u0000\u0000\u0569\u1a6e\u0001\u0000\u0000\u0000"+ + "\u056b\u1a74\u0001\u0000\u0000\u0000\u056d\u1a79\u0001\u0000\u0000\u0000"+ + "\u056f\u1a7e\u0001\u0000\u0000\u0000\u0571\u1a8f\u0001\u0000\u0000\u0000"+ + "\u0573\u1a91\u0001\u0000\u0000\u0000\u0575\u0576\u0005#\u0000\u0000\u0576"+ "\u0577\u0005{\u0000\u0000\u0577\u0578\u0001\u0000\u0000\u0000\u0578\u0579"+ "\u0003\u0007\u0001\u0000\u0579\u057a\u0005}\u0000\u0000\u057a\u0006\u0001"+ "\u0000\u0000\u0000\u057b\u057d\t\u0000\u0000\u0000\u057c\u057b\u0001\u0000"+ @@ -4153,1074 +4152,1071 @@ public class PostgreSqlLexer extends PostgreSqlLexerBase { "\u0000\u1250\u1251\u0007\r\u0000\u0000\u1251\u1252\u0007\n\u0000\u0000"+ "\u1252\u1253\u0007\t\u0000\u0000\u1253\u1254\u0007\t\u0000\u0000\u1254"+ "\u1255\u0007\u0011\u0000\u0000\u1255\u1256\u0007\u0013\u0000\u0000\u1256"+ - "\u1257\u0007\u0007\u0000\u0000\u1257\u037c\u0001\u0000\u0000"; + "\u1257\u0007\u0007\u0000\u0000\u1257\u037c\u0001\u0000\u0000\u0000\u1258"+ + "\u1259\u0007\u0017\u0000\u0000\u1259\u125a\u0007\n\u0000"; private static final String _serializedATNSegment2 = - "\u0000\u1258\u1259\u0007\u0017\u0000\u0000\u1259\u125a\u0007\n\u0000\u0000"+ - "\u125a\u125b\u0007\u0007\u0000\u0000\u125b\u125c\u0007\n\u0000\u0000\u125c"+ - "\u125d\u0007\r\u0000\u0000\u125d\u125e\u0007\u0005\u0000\u0000\u125e\u125f"+ - "\u0007\u0010\u0000\u0000\u125f\u1260\u0007\n\u0000\u0000\u1260\u1261\u0007"+ - "\f\u0000\u0000\u1261\u037e\u0001\u0000\u0000\u0000\u1262\u1263\u0007\u0006"+ - "\u0000\u0000\u1263\u1264\u0007\u0013\u0000\u0000\u1264\u1265\u0007\u0017"+ - "\u0000\u0000\u1265\u1266\u0007\u0017\u0000\u0000\u1266\u1267\u0007\n\u0000"+ - "\u0000\u1267\u1268\u0007\f\u0000\u0000\u1268\u0380\u0001\u0000\u0000\u0000"+ - "\u1269\u126a\u0007\t\u0000\u0000\u126a\u126b\u0007\u0010\u0000\u0000\u126b"+ - "\u126c\u0007\u0013\u0000\u0000\u126c\u126d\u0007\r\u0000\u0000\u126d\u126e"+ - "\u0007\n\u0000\u0000\u126e\u126f\u0007\f\u0000\u0000\u126f\u0382\u0001"+ - "\u0000\u0000\u0000\u1270\u1271\u0007\u0011\u0000\u0000\u1271\u1272\u0007"+ - "\u0007\u0000\u0000\u1272\u1273\u0007\u000e\u0000\u0000\u1273\u1274\u0007"+ - "\u0006\u0000\u0000\u1274\u1275\u0007\u0016\u0000\u0000\u1275\u1276\u0007"+ - "\f\u0000\u0000\u1276\u1277\u0007\n\u0000\u0000\u1277\u0384\u0001\u0000"+ - "\u0000\u0000\u1278\u1279\u0007\r\u0000\u0000\u1279\u127a\u0007\u0013\u0000"+ - "\u0000\u127a\u127b\u0007\u0016\u0000\u0000\u127b\u127c\u0007\u0010\u0000"+ - "\u0000\u127c\u127d\u0007\u0011\u0000\u0000\u127d\u127e\u0007\u0007\u0000"+ - "\u0000\u127e\u127f\u0007\n\u0000\u0000\u127f\u0386\u0001\u0000\u0000\u0000"+ - "\u1280\u1281\u0007\u0010\u0000\u0000\u1281\u1282\u0007\r\u0000\u0000\u1282"+ - "\u1283\u0007\u0005\u0000\u0000\u1283\u1284\u0007\u0007\u0000\u0000\u1284"+ - "\u1285\u0007\t\u0000\u0000\u1285\u1286\u0007\u0019\u0000\u0000\u1286\u1287"+ - "\u0007\u0013\u0000\u0000\u1287\u1288\u0007\r\u0000\u0000\u1288\u1289\u0007"+ - "\u000f\u0000\u0000\u1289\u0388\u0001\u0000\u0000\u0000\u128a\u128b\u0007"+ - "\u0011\u0000\u0000\u128b\u128c\u0007\u000f\u0000\u0000\u128c\u128d\u0007"+ - "\u0018\u0000\u0000\u128d\u128e\u0007\u0013\u0000\u0000\u128e\u128f\u0007"+ - "\r\u0000\u0000\u128f\u1290\u0007\u0010\u0000\u0000\u1290\u038a\u0001\u0000"+ - "\u0000\u0000\u1291\u1292\u0007\u0018\u0000\u0000\u1292\u1293\u0007\u0013"+ - "\u0000\u0000\u1293\u1294\u0007\u0006\u0000\u0000\u1294\u1295\u0007\u0011"+ - "\u0000\u0000\u1295\u1296\u0007\u000e\u0000\u0000\u1296\u1297\u0007\b\u0000"+ - "\u0000\u1297\u038c\u0001\u0000\u0000\u0000\u1298\u1299\u0007\u000f\u0000"+ - "\u0000\u1299\u129a\u0007\n\u0000\u0000\u129a\u129b\u0007\u0010\u0000\u0000"+ - "\u129b\u129c\u0007\u0014\u0000\u0000\u129c\u129d\u0007\u0013\u0000\u0000"+ - "\u129d\u129e\u0007\f\u0000\u0000\u129e\u038e\u0001\u0000\u0000\u0000\u129f"+ - "\u12a0\u0007\r\u0000\u0000\u12a0\u12a1\u0007\n\u0000\u0000\u12a1\u12a2"+ - "\u0007\u0019\u0000\u0000\u12a2\u12a3\u0007\n\u0000\u0000\u12a3\u12a4\u0007"+ - "\r\u0000\u0000\u12a4\u12a5\u0007\n\u0000\u0000\u12a5\u12a6\u0007\u0007"+ - "\u0000\u0000\u12a6\u12a7\u0007\u000e\u0000\u0000\u12a7\u12a8\u0007\u0011"+ - "\u0000\u0000\u12a8\u12a9\u0007\u0007\u0000\u0000\u12a9\u12aa\u0007\u0017"+ - "\u0000\u0000\u12aa\u0390\u0001\u0000\u0000\u0000\u12ab\u12ac\u0007\u0007"+ - "\u0000\u0000\u12ac\u12ad\u0007\n\u0000\u0000\u12ad\u12ae\u0007\u001d\u0000"+ - "\u0000\u12ae\u0392\u0001\u0000\u0000\u0000\u12af\u12b0\u0007\u0013\u0000"+ - "\u0000\u12b0\u12b1\u0007\u0006\u0000\u0000\u12b1\u12b2\u0007\f\u0000\u0000"+ - "\u12b2\u0394\u0001\u0000\u0000\u0000\u12b3\u12b4\u0007\u001b\u0000\u0000"+ - "\u12b4\u12b5\u0007\u0005\u0000\u0000\u12b5\u12b6\u0007\u0006\u0000\u0000"+ - "\u12b6\u12b7\u0007\u0016\u0000\u0000\u12b7\u12b8\u0007\n\u0000\u0000\u12b8"+ - "\u0396\u0001\u0000\u0000\u0000\u12b9\u12ba\u0007\t\u0000\u0000\u12ba\u12bb"+ - "\u0007\u0016\u0000\u0000\u12bb\u12bc\u0007\u0012\u0000\u0000\u12bc\u12bd"+ - "\u0007\t\u0000\u0000\u12bd\u12be\u0007\u000e\u0000\u0000\u12be\u12bf\u0007"+ - "\r\u0000\u0000\u12bf\u12c0\u0007\u0011\u0000\u0000\u12c0\u12c1\u0007\u0018"+ - "\u0000\u0000\u12c1\u12c2\u0007\u0010\u0000\u0000\u12c2\u12c3\u0007\u0011"+ - "\u0000\u0000\u12c3\u12c4\u0007\u0013\u0000\u0000\u12c4\u12c5\u0007\u0007"+ - "\u0000\u0000\u12c5\u0398\u0001\u0000\u0000\u0000\u12c6\u12c7\u0007\u0018"+ - "\u0000\u0000\u12c7\u12c8\u0007\u0016\u0000\u0000\u12c8\u12c9\u0007\u0012"+ - "\u0000\u0000\u12c9\u12ca\u0007\u0006\u0000\u0000\u12ca\u12cb\u0007\u0011"+ - "\u0000\u0000\u12cb\u12cc\u0007\u000e\u0000\u0000\u12cc\u12cd\u0007\u0005"+ - "\u0000\u0000\u12cd\u12ce\u0007\u0010\u0000\u0000\u12ce\u12cf\u0007\u0011"+ - "\u0000\u0000\u12cf\u12d0\u0007\u0013\u0000\u0000\u12d0\u12d1\u0007\u0007"+ - "\u0000\u0000\u12d1\u039a\u0001\u0000\u0000\u0000\u12d2\u12d3\u0007\u0013"+ - "\u0000\u0000\u12d3\u12d4\u0007\u0016\u0000\u0000\u12d4\u12d5\u0007\u0010"+ - "\u0000\u0000\u12d5\u039c\u0001\u0000\u0000\u0000\u12d6\u12d7\u0007\n\u0000"+ - "\u0000\u12d7\u12d8\u0007\u0007\u0000\u0000\u12d8\u12d9\u0007\f\u0000\u0000"+ - "\u12d9\u039e\u0001\u0000\u0000\u0000\u12da\u12db\u0007\r\u0000\u0000\u12db"+ - "\u12dc\u0007\u0013\u0000\u0000\u12dc\u12dd\u0007\u0016\u0000\u0000\u12dd"+ - "\u12de\u0007\u0010\u0000\u0000\u12de\u12df\u0007\u0011\u0000\u0000\u12df"+ - "\u12e0\u0007\u0007\u0000\u0000\u12e0\u12e1\u0007\n\u0000\u0000\u12e1\u12e2"+ - "\u0007\t\u0000\u0000\u12e2\u03a0\u0001\u0000\u0000\u0000\u12e3\u12e4\u0007"+ - "\t\u0000\u0000\u12e4\u12e5\u0007\u000e\u0000\u0000\u12e5\u12e6\u0007\u0014"+ - "\u0000\u0000\u12e6\u12e7\u0007\n\u0000\u0000\u12e7\u12e8\u0007\u000f\u0000"+ - "\u0000\u12e8\u12e9\u0007\u0005\u0000\u0000\u12e9\u12ea\u0007\t\u0000\u0000"+ - "\u12ea\u03a2\u0001\u0000\u0000\u0000\u12eb\u12ec\u0007\u0018\u0000\u0000"+ - "\u12ec\u12ed\u0007\r\u0000\u0000\u12ed\u12ee\u0007\u0013\u0000\u0000\u12ee"+ - "\u12ef\u0007\u000e\u0000\u0000\u12ef\u12f0\u0007\n\u0000\u0000\u12f0\u12f1"+ - "\u0007\f\u0000\u0000\u12f1\u12f2\u0007\u0016\u0000\u0000\u12f2\u12f3\u0007"+ - "\r\u0000\u0000\u12f3\u12f4\u0007\n\u0000\u0000\u12f4\u12f5\u0007\t\u0000"+ - "\u0000\u12f5\u03a4\u0001\u0000\u0000\u0000\u12f6\u12f7\u0007\u0011\u0000"+ - "\u0000\u12f7\u12f8\u0007\u0007\u0000\u0000\u12f8\u12f9\u0007\u0018\u0000"+ - "\u0000\u12f9\u12fa\u0007\u0016\u0000\u0000\u12fa\u12fb\u0007\u0010\u0000"+ - "\u0000\u12fb\u03a6\u0001\u0000\u0000\u0000\u12fc\u12fd\u0007\t\u0000\u0000"+ - "\u12fd\u12fe\u0007\u0016\u0000\u0000\u12fe\u12ff\u0007\u0018\u0000\u0000"+ - "\u12ff\u1300\u0007\u0018\u0000\u0000\u1300\u1301\u0007\u0013\u0000\u0000"+ - "\u1301\u1302\u0007\r\u0000\u0000\u1302\u1303\u0007\u0010\u0000\u0000\u1303"+ - "\u03a8\u0001\u0000\u0000\u0000\u1304\u1305\u0007\u0018\u0000\u0000\u1305"+ - "\u1306\u0007\u0005\u0000\u0000\u1306\u1307\u0007\r\u0000\u0000\u1307\u1308"+ - "\u0007\u0005\u0000\u0000\u1308\u1309\u0007\u0006\u0000\u0000\u1309\u130a"+ - "\u0007\u0006\u0000\u0000\u130a\u130b\u0007\n\u0000\u0000\u130b\u130c\u0007"+ - "\u0006\u0000\u0000\u130c\u03aa\u0001\u0000\u0000\u0000\u130d\u130e\u0007"+ - "\t\u0000\u0000\u130e\u130f\u0007\u001c\u0000\u0000\u130f\u1310\u0007\u0006"+ - "\u0000\u0000\u1310\u03ac\u0001\u0000\u0000\u0000\u1311\u1312\u0007\f\u0000"+ - "\u0000\u1312\u1313\u0007\n\u0000\u0000\u1313\u1314\u0007\u0018\u0000\u0000"+ - "\u1314\u1315\u0007\n\u0000\u0000\u1315\u1316\u0007\u0007\u0000\u0000\u1316"+ - "\u1317\u0007\f\u0000\u0000\u1317\u1318\u0007\t\u0000\u0000\u1318\u03ae"+ - "\u0001\u0000\u0000\u0000\u1319\u131a\u0007\u0013\u0000\u0000\u131a\u131b"+ - "\u0007\u001b\u0000\u0000\u131b\u131c\u0007\n\u0000\u0000\u131c\u131d\u0007"+ - "\r\u0000\u0000\u131d\u131e\u0007\r\u0000\u0000\u131e\u131f\u0007\u0011"+ - "\u0000\u0000\u131f\u1320\u0007\f\u0000\u0000\u1320\u1321\u0007\u0011\u0000"+ - "\u0000\u1321\u1322\u0007\u0007\u0000\u0000\u1322\u1323\u0007\u0017\u0000"+ - "\u0000\u1323\u03b0\u0001\u0000\u0000\u0000\u1324\u1325\u0007\u000e\u0000"+ - "\u0000\u1325\u1326\u0007\u0013\u0000\u0000\u1326\u1327\u0007\u0007\u0000"+ - "\u0000\u1327\u1328\u0007\u0019\u0000\u0000\u1328\u1329\u0007\u0006\u0000"+ - "\u0000\u1329\u132a\u0007\u0011\u0000\u0000\u132a\u132b\u0007\u000e\u0000"+ - "\u0000\u132b\u132c\u0007\u0010\u0000\u0000\u132c\u03b2\u0001\u0000\u0000"+ - "\u0000\u132d\u132e\u0007\t\u0000\u0000\u132e\u132f\u0007\u0015\u0000\u0000"+ - "\u132f\u1330\u0007\u0011\u0000\u0000\u1330\u1331\u0007\u0018\u0000\u0000"+ - "\u1331\u03b4\u0001\u0000\u0000\u0000\u1332\u1333\u0007\u0006\u0000\u0000"+ - "\u1333\u1334\u0007\u0013\u0000\u0000\u1334\u1335\u0007\u000e\u0000\u0000"+ - "\u1335\u1336\u0007\u0015\u0000\u0000\u1336\u1337\u0007\n\u0000\u0000\u1337"+ - "\u1338\u0007\f\u0000\u0000\u1338\u03b6\u0001\u0000\u0000\u0000\u1339\u133a"+ - "\u0007\u0010\u0000\u0000\u133a\u133b\u0007\u0011\u0000\u0000\u133b\u133c"+ - "\u0007\n\u0000\u0000\u133c\u133d\u0007\t\u0000\u0000\u133d\u03b8\u0001"+ - "\u0000\u0000\u0000\u133e\u133f\u0007\r\u0000\u0000\u133f\u1340\u0007\u0013"+ - "\u0000\u0000\u1340\u1341\u0007\u0006\u0000\u0000\u1341\u1342\u0007\u0006"+ - "\u0000\u0000\u1342\u1343\u0007\u0016\u0000\u0000\u1343\u1344\u0007\u0018"+ - "\u0000\u0000\u1344\u03ba\u0001\u0000\u0000\u0000\u1345\u1346\u0007\u000e"+ - "\u0000\u0000\u1346\u1347\u0007\u0016\u0000\u0000\u1347\u1348\u0007\u0012"+ - "\u0000\u0000\u1348\u1349\u0007\n\u0000\u0000\u1349\u03bc\u0001\u0000\u0000"+ - "\u0000\u134a\u134b\u0007\u0017\u0000\u0000\u134b\u134c\u0007\r\u0000\u0000"+ - "\u134c\u134d\u0007\u0013\u0000\u0000\u134d\u134e\u0007\u0016\u0000\u0000"+ - "\u134e\u134f\u0007\u0018\u0000\u0000\u134f\u1350\u0007\u0011\u0000\u0000"+ - "\u1350\u1351\u0007\u0007\u0000\u0000\u1351\u1352\u0007\u0017\u0000\u0000"+ - "\u1352\u03be\u0001\u0000\u0000\u0000\u1353\u1354\u0007\t\u0000\u0000\u1354"+ - "\u1355\u0007\n\u0000\u0000\u1355\u1356\u0007\u0010\u0000\u0000\u1356\u1357"+ - "\u0007\t\u0000\u0000\u1357\u03c0\u0001\u0000\u0000\u0000\u1358\u1359\u0007"+ - "\u0010\u0000\u0000\u1359\u135a\u0007\u0005\u0000\u0000\u135a\u135b\u0007"+ - "\u0012\u0000\u0000\u135b\u135c\u0007\u0006\u0000\u0000\u135c\u135d\u0007"+ - "\n\u0000\u0000\u135d\u135e\u0007\t\u0000\u0000\u135e\u135f\u0007\u0005"+ - "\u0000\u0000\u135f\u1360\u0007\u000f\u0000\u0000\u1360\u1361\u0007\u0018"+ - "\u0000\u0000\u1361\u1362\u0007\u0006\u0000\u0000\u1362\u1363\u0007\n\u0000"+ - "\u0000\u1363\u03c2\u0001\u0000\u0000\u0000\u1364\u1365\u0007\u0013\u0000"+ - "\u0000\u1365\u1366\u0007\r\u0000\u0000\u1366\u1367\u0007\f\u0000\u0000"+ - "\u1367\u1368\u0007\u0011\u0000\u0000\u1368\u1369\u0007\u0007\u0000\u0000"+ - "\u1369\u136a\u0007\u0005\u0000\u0000\u136a\u136b\u0007\u0006\u0000\u0000"+ - "\u136b\u136c\u0007\u0011\u0000\u0000\u136c\u136d\u0007\u0010\u0000\u0000"+ - "\u136d\u136e\u0007\b\u0000\u0000\u136e\u03c4\u0001\u0000\u0000\u0000\u136f"+ - "\u1370\u0007\u001a\u0000\u0000\u1370\u1371\u0007\u000f\u0000\u0000\u1371"+ - "\u1372\u0007\u0006\u0000\u0000\u1372\u1373\u0007\u0010\u0000\u0000\u1373"+ - "\u1374\u0007\u0005\u0000\u0000\u1374\u1375\u0007\u0012\u0000\u0000\u1375"+ - "\u1376\u0007\u0006\u0000\u0000\u1376\u1377\u0007\n\u0000\u0000\u1377\u03c6"+ - "\u0001\u0000\u0000\u0000\u1378\u1379\u0007\u000e\u0000\u0000\u1379\u137a"+ - "\u0007\u0013\u0000\u0000\u137a\u137b\u0007\u0006\u0000\u0000\u137b\u137c"+ - "\u0007\u0016\u0000\u0000\u137c\u137d\u0007\u000f\u0000\u0000\u137d\u137e"+ - "\u0007\u0007\u0000\u0000\u137e\u137f\u0007\t\u0000\u0000\u137f\u03c8\u0001"+ - "\u0000\u0000\u0000\u1380\u1381\u0007\u001a\u0000\u0000\u1381\u1382\u0007"+ - "\u000f\u0000\u0000\u1382\u1383\u0007\u0006\u0000\u0000\u1383\u1384\u0007"+ - "\u0007\u0000\u0000\u1384\u1385\u0007\u0005\u0000\u0000\u1385\u1386\u0007"+ - "\u000f\u0000\u0000\u1386\u1387\u0007\n\u0000\u0000\u1387\u1388\u0007\t"+ - "\u0000\u0000\u1388\u1389\u0007\u0018\u0000\u0000\u1389\u138a\u0007\u0005"+ - "\u0000\u0000\u138a\u138b\u0007\u000e\u0000\u0000\u138b\u138c\u0007\n\u0000"+ - "\u0000\u138c\u138d\u0007\t\u0000\u0000\u138d\u03ca\u0001\u0000\u0000\u0000"+ - "\u138e\u138f\u0007\r\u0000\u0000\u138f\u1390\u0007\u0013\u0000\u0000\u1390"+ - "\u1391\u0007\u001d\u0000\u0000\u1391\u1392\u0007\u0010\u0000\u0000\u1392"+ - "\u1393\u0007\b\u0000\u0000\u1393\u1394\u0007\u0018\u0000\u0000\u1394\u1395"+ - "\u0007\n\u0000\u0000\u1395\u03cc\u0001\u0000\u0000\u0000\u1396\u1397\u0007"+ - "\u0007\u0000\u0000\u1397\u1398\u0007\u0013\u0000\u0000\u1398\u1399\u0007"+ - "\r\u0000\u0000\u1399\u139a\u0007\u000f\u0000\u0000\u139a\u139b\u0007\u0005"+ - "\u0000\u0000\u139b\u139c\u0007\u0006\u0000\u0000\u139c\u139d\u0007\u0011"+ - "\u0000\u0000\u139d\u139e\u0007\u000b\u0000\u0000\u139e\u139f\u0007\n\u0000"+ - "\u0000\u139f\u13a0\u0007\f\u0000\u0000\u13a0\u03ce\u0001\u0000\u0000\u0000"+ - "\u13a1\u13a2\u0007\u001d\u0000\u0000\u13a2\u13a3\u0007\u0011\u0000\u0000"+ - "\u13a3\u13a4\u0007\u0010\u0000\u0000\u13a4\u13a5\u0007\u0014\u0000\u0000"+ - "\u13a5\u13a6\u0007\u0011\u0000\u0000\u13a6\u13a7\u0007\u0007\u0000\u0000"+ - "\u13a7\u03d0\u0001\u0000\u0000\u0000\u13a8\u13a9\u0007\u0019\u0000\u0000"+ - "\u13a9\u13aa\u0007\u0011\u0000\u0000\u13aa\u13ab\u0007\u0006\u0000\u0000"+ - "\u13ab\u13ac\u0007\u0010\u0000\u0000\u13ac\u13ad\u0007\n\u0000\u0000\u13ad"+ - "\u13ae\u0007\r\u0000\u0000\u13ae\u03d2\u0001\u0000\u0000\u0000\u13af\u13b0"+ - "\u0007\u0017\u0000\u0000\u13b0\u13b1\u0007\r\u0000\u0000\u13b1\u13b2\u0007"+ - "\u0013\u0000\u0000\u13b2\u13b3\u0007\u0016\u0000\u0000\u13b3\u13b4\u0007"+ - "\u0018\u0000\u0000\u13b4\u13b5\u0007\t\u0000\u0000\u13b5\u03d4\u0001\u0000"+ - "\u0000\u0000\u13b6\u13b7\u0007\u0013\u0000\u0000\u13b7\u13b8\u0007\u0010"+ - "\u0000\u0000\u13b8\u13b9\u0007\u0014\u0000\u0000\u13b9\u13ba\u0007\n\u0000"+ - "\u0000\u13ba\u13bb\u0007\r\u0000\u0000\u13bb\u13bc\u0007\t\u0000\u0000"+ - "\u13bc\u03d6\u0001\u0000\u0000\u0000\u13bd\u13be\u0007\u0007\u0000\u0000"+ - "\u13be\u13bf\u0007\u0019\u0000\u0000\u13bf\u13c0\u0007\u000e\u0000\u0000"+ - "\u13c0\u03d8\u0001\u0000\u0000\u0000\u13c1\u13c2\u0007\u0007\u0000\u0000"+ - "\u13c2\u13c3\u0007\u0019\u0000\u0000\u13c3\u13c4\u0007\f\u0000\u0000\u13c4"+ - "\u03da\u0001\u0000\u0000\u0000\u13c5\u13c6\u0007\u0007\u0000\u0000\u13c6"+ - "\u13c7\u0007\u0019\u0000\u0000\u13c7\u13c8\u0007\u0015\u0000\u0000\u13c8"+ - "\u13c9\u0007\u000e\u0000\u0000\u13c9\u03dc\u0001\u0000\u0000\u0000\u13ca"+ - "\u13cb\u0007\u0007\u0000\u0000\u13cb\u13cc\u0007\u0019\u0000\u0000\u13cc"+ - "\u13cd\u0007\u0015\u0000\u0000\u13cd\u13ce\u0007\f\u0000\u0000\u13ce\u03de"+ - "\u0001\u0000\u0000\u0000\u13cf\u13d0\u0007\u0016\u0000\u0000\u13d0\u13d1"+ - "\u0007\n\u0000\u0000\u13d1\u13d2\u0007\t\u0000\u0000\u13d2\u13d3\u0007"+ - "\u000e\u0000\u0000\u13d3\u13d4\u0007\u0005\u0000\u0000\u13d4\u13d5\u0007"+ - "\u0018\u0000\u0000\u13d5\u13d6\u0007\n\u0000\u0000\u13d6\u03e0\u0001\u0000"+ - "\u0000\u0000\u13d7\u13d8\u0007\u001b\u0000\u0000\u13d8\u13d9\u0007\u0011"+ - "\u0000\u0000\u13d9\u13da\u0007\n\u0000\u0000\u13da\u13db\u0007\u001d\u0000"+ - "\u0000\u13db\u13dc\u0007\t\u0000\u0000\u13dc\u03e2\u0001\u0000\u0000\u0000"+ - "\u13dd\u13de\u0007\u0007\u0000\u0000\u13de\u13df\u0007\u0013\u0000\u0000"+ - "\u13df\u13e0\u0007\r\u0000\u0000\u13e0\u13e1\u0007\u000f\u0000\u0000\u13e1"+ - "\u13e2\u0007\u0005\u0000\u0000\u13e2\u13e3\u0007\u0006\u0000\u0000\u13e3"+ - "\u13e4\u0007\u0011\u0000\u0000\u13e4\u13e5\u0007\u000b\u0000\u0000\u13e5"+ - "\u13e6\u0007\n\u0000\u0000\u13e6\u03e4\u0001\u0000\u0000\u0000\u13e7\u13e8"+ - "\u0007\f\u0000\u0000\u13e8\u13e9\u0007\u0016\u0000\u0000\u13e9\u13ea\u0007"+ - "\u000f\u0000\u0000\u13ea\u13eb\u0007\u0018\u0000\u0000\u13eb\u03e6\u0001"+ - "\u0000\u0000\u0000\u13ec\u13ed\u0007\u0018\u0000\u0000\u13ed\u13ee\u0007"+ - "\r\u0000\u0000\u13ee\u13ef\u0007\u0011\u0000\u0000\u13ef\u13f0\u0007\u0007"+ - "\u0000\u0000\u13f0\u13f1\u0007\u0010\u0000\u0000\u13f1\u13f2\u0005_\u0000"+ - "\u0000\u13f2\u13f3\u0007\t\u0000\u0000\u13f3\u13f4\u0007\u0010\u0000\u0000"+ - "\u13f4\u13f5\u0007\r\u0000\u0000\u13f5\u13f6\u0007\u0011\u0000\u0000\u13f6"+ - "\u13f7\u0007\u000e\u0000\u0000\u13f7\u13f8\u0007\u0010\u0000\u0000\u13f8"+ - "\u13f9\u0005_\u0000\u0000\u13f9\u13fa\u0007\u0018\u0000\u0000\u13fa\u13fb"+ - "\u0007\u0005\u0000\u0000\u13fb\u13fc\u0007\r\u0000\u0000\u13fc\u13fd\u0007"+ - "\u0005\u0000\u0000\u13fd\u13fe\u0007\u000f\u0000\u0000\u13fe\u13ff\u0007"+ - "\t\u0000\u0000\u13ff\u03e8\u0001\u0000\u0000\u0000\u1400\u1401\u0007\u001b"+ - "\u0000\u0000\u1401\u1402\u0007\u0005\u0000\u0000\u1402\u1403\u0007\r\u0000"+ - "\u0000\u1403\u1404\u0007\u0011\u0000\u0000\u1404\u1405\u0007\u0005\u0000"+ - "\u0000\u1405\u1406\u0007\u0012\u0000\u0000\u1406\u1407\u0007\u0006\u0000"+ - "\u0000\u1407\u1408\u0007\n\u0000\u0000\u1408\u1409\u0005_\u0000\u0000"+ - "\u1409\u140a\u0007\u000e\u0000\u0000\u140a\u140b\u0007\u0013\u0000\u0000"+ - "\u140b\u140c\u0007\u0007\u0000\u0000\u140c\u140d\u0007\u0019\u0000\u0000"+ - "\u140d\u140e\u0007\u0006\u0000\u0000\u140e\u140f\u0007\u0011\u0000\u0000"+ - "\u140f\u1410\u0007\u000e\u0000\u0000\u1410\u1411\u0007\u0010\u0000\u0000"+ - "\u1411\u03ea\u0001\u0000\u0000\u0000\u1412\u1413\u0007\n\u0000\u0000\u1413"+ - "\u1414\u0007\r\u0000\u0000\u1414\u1415\u0007\r\u0000\u0000\u1415\u1416"+ - "\u0007\u0013\u0000\u0000\u1416\u1417\u0007\r\u0000\u0000\u1417\u03ec\u0001"+ - "\u0000\u0000\u0000\u1418\u1419\u0007\u0016\u0000\u0000\u1419\u141a\u0007"+ - "\t\u0000\u0000\u141a\u141b\u0007\n\u0000\u0000\u141b\u141c\u0005_\u0000"+ - "\u0000\u141c\u141d\u0007\u001b\u0000\u0000\u141d\u141e\u0007\u0005\u0000"+ - "\u0000\u141e\u141f\u0007\r\u0000\u0000\u141f\u1420\u0007\u0011\u0000\u0000"+ - "\u1420\u1421\u0007\u0005\u0000\u0000\u1421\u1422\u0007\u0012\u0000\u0000"+ - "\u1422\u1423\u0007\u0006\u0000\u0000\u1423\u1424\u0007\n\u0000\u0000\u1424"+ - "\u03ee\u0001\u0000\u0000\u0000\u1425\u1426\u0007\u0016\u0000\u0000\u1426"+ - "\u1427\u0007\t\u0000\u0000\u1427\u1428\u0007\n\u0000\u0000\u1428\u1429"+ - "\u0005_\u0000\u0000\u1429\u142a\u0007\u000e\u0000\u0000\u142a\u142b\u0007"+ - "\u0013\u0000\u0000\u142b\u142c\u0007\u0006\u0000\u0000\u142c\u142d\u0007"+ - "\u0016\u0000\u0000\u142d\u142e\u0007\u000f\u0000\u0000\u142e\u142f\u0007"+ - "\u0007\u0000\u0000\u142f\u03f0\u0001\u0000\u0000\u0000\u1430\u1431\u0007"+ - "\u0005\u0000\u0000\u1431\u1432\u0007\u0006\u0000\u0000\u1432\u1433\u0007"+ - "\u0011\u0000\u0000\u1433\u1434\u0007\u0005\u0000\u0000\u1434\u1435\u0007"+ - "\t\u0000\u0000\u1435\u03f2\u0001\u0000\u0000\u0000\u1436\u1437\u0007\u000e"+ - "\u0000\u0000\u1437\u1438\u0007\u0013\u0000\u0000\u1438\u1439\u0007\u0007"+ - "\u0000\u0000\u1439\u143a\u0007\t\u0000\u0000\u143a\u143b\u0007\u0010\u0000"+ - "\u0000\u143b\u143c\u0007\u0005\u0000\u0000\u143c\u143d\u0007\u0007\u0000"+ - "\u0000\u143d\u143e\u0007\u0010\u0000\u0000\u143e\u03f4\u0001\u0000\u0000"+ - "\u0000\u143f\u1440\u0007\u0018\u0000\u0000\u1440\u1441\u0007\n\u0000\u0000"+ - "\u1441\u1442\u0007\r\u0000\u0000\u1442\u1443\u0007\u0019\u0000\u0000\u1443"+ - "\u1444\u0007\u0013\u0000\u0000\u1444\u1445\u0007\r\u0000\u0000\u1445\u1446"+ - "\u0007\u000f\u0000\u0000\u1446\u03f6\u0001\u0000\u0000\u0000\u1447\u1448"+ - "\u0007\u0017\u0000\u0000\u1448\u1449\u0007\n\u0000\u0000\u1449\u144a\u0007"+ - "\u0010\u0000\u0000\u144a\u03f8\u0001\u0000\u0000\u0000\u144b\u144c\u0007"+ - "\f\u0000\u0000\u144c\u144d\u0007\u0011\u0000\u0000\u144d\u144e\u0007\u0005"+ - "\u0000\u0000\u144e\u144f\u0007\u0017\u0000\u0000\u144f\u1450\u0007\u0007"+ - "\u0000\u0000\u1450\u1451\u0007\u0013\u0000\u0000\u1451\u1452\u0007\t\u0000"+ - "\u0000\u1452\u1453\u0007\u0010\u0000\u0000\u1453\u1454\u0007\u0011\u0000"+ - "\u0000\u1454\u1455\u0007\u000e\u0000\u0000\u1455\u1456\u0007\t\u0000\u0000"+ - "\u1456\u03fa\u0001\u0000\u0000\u0000\u1457\u1458\u0007\t\u0000\u0000\u1458"+ - "\u1459\u0007\u0010\u0000\u0000\u1459\u145a\u0007\u0005\u0000\u0000\u145a"+ - "\u145b\u0007\u000e\u0000\u0000\u145b\u145c\u0007\u0015\u0000\u0000\u145c"+ - "\u145d\u0007\n\u0000\u0000\u145d\u145e\u0007\f\u0000\u0000\u145e\u03fc"+ - "\u0001\u0000\u0000\u0000\u145f\u1460\u0007\n\u0000\u0000\u1460\u1461\u0007"+ - "\u0006\u0000\u0000\u1461\u1462\u0007\t\u0000\u0000\u1462\u1463\u0007\u0011"+ - "\u0000\u0000\u1463\u1464\u0007\u0019\u0000\u0000\u1464\u03fe\u0001\u0000"+ - "\u0000\u0000\u1465\u1466\u0007\u001d\u0000\u0000\u1466\u1467\u0007\u0014"+ - "\u0000\u0000\u1467\u1468\u0007\u0011\u0000\u0000\u1468\u1469\u0007\u0006"+ - "\u0000\u0000\u1469\u146a\u0007\n\u0000\u0000\u146a\u0400\u0001\u0000\u0000"+ - "\u0000\u146b\u146c\u0007\r\u0000\u0000\u146c\u146d\u0007\n\u0000\u0000"+ - "\u146d\u146e\u0007\u001b\u0000\u0000\u146e\u146f\u0007\n\u0000\u0000\u146f"+ - "\u1470\u0007\r\u0000\u0000\u1470\u1471\u0007\t\u0000\u0000\u1471\u1472"+ - "\u0007\n\u0000\u0000\u1472\u0402\u0001\u0000\u0000\u0000\u1473\u1474\u0007"+ - "\u0019\u0000\u0000\u1474\u1475\u0007\u0013\u0000\u0000\u1475\u1476\u0007"+ - "\r\u0000\u0000\u1476\u1477\u0007\n\u0000\u0000\u1477\u1478\u0007\u0005"+ - "\u0000\u0000\u1478\u1479\u0007\u000e\u0000\u0000\u1479\u147a\u0007\u0014"+ - "\u0000\u0000\u147a\u0404\u0001\u0000\u0000\u0000\u147b\u147c\u0007\t\u0000"+ - "\u0000\u147c\u147d\u0007\u0006\u0000\u0000\u147d\u147e\u0007\u0011\u0000"+ - "\u0000\u147e\u147f\u0007\u000e\u0000\u0000\u147f\u1480\u0007\n\u0000\u0000"+ - "\u1480\u0406\u0001\u0000\u0000\u0000\u1481\u1482\u0007\n\u0000\u0000\u1482"+ - "\u1483\u0007\u001a\u0000\u0000\u1483\u1484\u0007\u0011\u0000\u0000\u1484"+ - "\u1485\u0007\u0010\u0000\u0000\u1485\u0408\u0001\u0000\u0000\u0000\u1486"+ - "\u1487\u0007\r\u0000\u0000\u1487\u1488\u0007\n\u0000\u0000\u1488\u1489"+ - "\u0007\u0010\u0000\u0000\u1489\u148a\u0007\u0016\u0000\u0000\u148a\u148b"+ - "\u0007\r\u0000\u0000\u148b\u148c\u0007\u0007\u0000\u0000\u148c\u040a\u0001"+ - "\u0000\u0000\u0000\u148d\u148e\u0007\u001c\u0000\u0000\u148e\u148f\u0007"+ - "\u0016\u0000\u0000\u148f\u1490\u0007\n\u0000\u0000\u1490\u1491\u0007\r"+ - "\u0000\u0000\u1491\u1492\u0007\b\u0000\u0000\u1492\u040c\u0001\u0000\u0000"+ - "\u0000\u1493\u1494\u0007\r\u0000\u0000\u1494\u1495\u0007\u0005\u0000\u0000"+ - "\u1495\u1496\u0007\u0011\u0000\u0000\u1496\u1497\u0007\t\u0000\u0000\u1497"+ - "\u1498\u0007\n\u0000\u0000\u1498\u040e\u0001\u0000\u0000\u0000\u1499\u149a"+ - "\u0007\t\u0000\u0000\u149a\u149b\u0007\u001c\u0000\u0000\u149b\u149c\u0007"+ - "\u0006\u0000\u0000\u149c\u149d\u0007\t\u0000\u0000\u149d\u149e\u0007\u0010"+ - "\u0000\u0000\u149e\u149f\u0007\u0005\u0000\u0000\u149f\u14a0\u0007\u0010"+ - "\u0000\u0000\u14a0\u14a1\u0007\n\u0000\u0000\u14a1\u0410\u0001\u0000\u0000"+ - "\u0000\u14a2\u14a3\u0007\f\u0000\u0000\u14a3\u14a4\u0007\n\u0000\u0000"+ - "\u14a4\u14a5\u0007\u0012\u0000\u0000\u14a5\u14a6\u0007\u0016\u0000\u0000"+ - "\u14a6\u14a7\u0007\u0017\u0000\u0000\u14a7\u0412\u0001\u0000\u0000\u0000"+ - "\u14a8\u14a9\u0007\u0006\u0000\u0000\u14a9\u14aa\u0007\u0013\u0000\u0000"+ - "\u14aa\u14ab\u0007\u0017\u0000\u0000\u14ab\u0414\u0001\u0000\u0000\u0000"+ - "\u14ac\u14ad\u0007\u0011\u0000\u0000\u14ad\u14ae\u0007\u0007\u0000\u0000"+ - "\u14ae\u14af\u0007\u0019\u0000\u0000\u14af\u14b0\u0007\u0013\u0000\u0000"+ - "\u14b0\u0416\u0001\u0000\u0000\u0000\u14b1\u14b2\u0007\u0007\u0000\u0000"+ - "\u14b2\u14b3\u0007\u0013\u0000\u0000\u14b3\u14b4\u0007\u0010\u0000\u0000"+ - "\u14b4\u14b5\u0007\u0011\u0000\u0000\u14b5\u14b6\u0007\u000e\u0000\u0000"+ - "\u14b6\u14b7\u0007\n\u0000\u0000\u14b7\u0418\u0001\u0000\u0000\u0000\u14b8"+ - "\u14b9\u0007\u001d\u0000\u0000\u14b9\u14ba\u0007\u0005\u0000\u0000\u14ba"+ - "\u14bb\u0007\r\u0000\u0000\u14bb\u14bc\u0007\u0007\u0000\u0000\u14bc\u14bd"+ - "\u0007\u0011\u0000\u0000\u14bd\u14be\u0007\u0007\u0000\u0000\u14be\u14bf"+ - "\u0007\u0017\u0000\u0000\u14bf\u041a\u0001\u0000\u0000\u0000\u14c0\u14c1"+ - "\u0007\n\u0000\u0000\u14c1\u14c2\u0007\u001a\u0000\u0000\u14c2\u14c3\u0007"+ - "\u000e\u0000\u0000\u14c3\u14c4\u0007\n\u0000\u0000\u14c4\u14c5\u0007\u0018"+ - "\u0000\u0000\u14c5\u14c6\u0007\u0010\u0000\u0000\u14c6\u14c7\u0007\u0011"+ - "\u0000\u0000\u14c7\u14c8\u0007\u0013\u0000\u0000\u14c8\u14c9\u0007\u0007"+ - "\u0000\u0000\u14c9\u041c\u0001\u0000\u0000\u0000\u14ca\u14cb\u0007\u0005"+ - "\u0000\u0000\u14cb\u14cc\u0007\t\u0000\u0000\u14cc\u14cd\u0007\t\u0000"+ - "\u0000\u14cd\u14ce\u0007\n\u0000\u0000\u14ce\u14cf\u0007\r\u0000\u0000"+ - "\u14cf\u14d0\u0007\u0010\u0000\u0000\u14d0\u041e\u0001\u0000\u0000\u0000"+ - "\u14d1\u14d2\u0007\u0006\u0000\u0000\u14d2\u14d3\u0007\u0013\u0000\u0000"+ - "\u14d3\u14d4\u0007\u0013\u0000\u0000\u14d4\u14d5\u0007\u0018\u0000\u0000"+ - "\u14d5\u0420\u0001\u0000\u0000\u0000\u14d6\u14d7\u0007\u0013\u0000\u0000"+ - "\u14d7\u14d8\u0007\u0018\u0000\u0000\u14d8\u14d9\u0007\n\u0000\u0000\u14d9"+ - "\u14da\u0007\u0007\u0000\u0000\u14da\u0422\u0001\u0000\u0000\u0000\u14db"+ - "\u14dc\u0007\u0010\u0000\u0000\u14dc\u14dd\u0007\u0013\u0000\u0000\u14dd"+ - "\u14de\u0007\u0018\u0000\u0000\u14de\u0424\u0001\u0000\u0000\u0000\u14df"+ - "\u14e0\u0007\u0005\u0000\u0000\u14e0\u14e1\u0007\u0012\u0000\u0000\u14e1"+ - "\u14e2\u0007\t\u0000\u0000\u14e2\u0426\u0001\u0000\u0000\u0000\u14e3\u14e4"+ - "\u0007\u000e\u0000\u0000\u14e4\u14e5\u0007\u0012\u0000\u0000\u14e5\u14e6"+ - "\u0007\r\u0000\u0000\u14e6\u14e7\u0007\u0010\u0000\u0000\u14e7\u0428\u0001"+ - "\u0000\u0000\u0000\u14e8\u14e9\u0007\u000e\u0000\u0000\u14e9\u14ea\u0007"+ - "\n\u0000\u0000\u14ea\u14eb\u0007\u0011\u0000\u0000\u14eb\u14ec\u0007\u0006"+ - "\u0000\u0000\u14ec\u042a\u0001\u0000\u0000\u0000\u14ed\u14ee\u0007\u000e"+ - "\u0000\u0000\u14ee\u14ef\u0007\n\u0000\u0000\u14ef\u14f0\u0007\u0011\u0000"+ - "\u0000\u14f0\u14f1\u0007\u0006\u0000\u0000\u14f1\u14f2\u0007\u0011\u0000"+ - "\u0000\u14f2\u14f3\u0007\u0007\u0000\u0000\u14f3\u14f4\u0007\u0017\u0000"+ - "\u0000\u14f4\u042c\u0001\u0000\u0000\u0000\u14f5\u14f6\u0007\f\u0000\u0000"+ - "\u14f6\u14f7\u0007\n\u0000\u0000\u14f7\u14f8\u0007\u0017\u0000\u0000\u14f8"+ - "\u14f9\u0007\r\u0000\u0000\u14f9\u14fa\u0007\n\u0000\u0000\u14fa\u14fb"+ - "\u0007\n\u0000\u0000\u14fb\u14fc\u0007\t\u0000\u0000\u14fc\u042e\u0001"+ - "\u0000\u0000\u0000\u14fd\u14fe\u0007\f\u0000\u0000\u14fe\u14ff\u0007\u0011"+ - "\u0000\u0000\u14ff\u1500\u0007\u001b\u0000\u0000\u1500\u0430\u0001\u0000"+ - "\u0000\u0000\u1501\u1502\u0007\n\u0000\u0000\u1502\u1503\u0007\u001a\u0000"+ - "\u0000\u1503\u1504\u0007\u0018\u0000\u0000\u1504\u0432\u0001\u0000\u0000"+ - "\u0000\u1505\u1506\u0007\u0019\u0000\u0000\u1506\u1507\u0007\u0005\u0000"+ - "\u0000\u1507\u1508\u0007\u000e\u0000\u0000\u1508\u1509\u0007\u0010\u0000"+ - "\u0000\u1509\u150a\u0007\u0013\u0000\u0000\u150a\u150b\u0007\r\u0000\u0000"+ - "\u150b\u150c\u0007\u0011\u0000\u0000\u150c\u150d\u0007\u0005\u0000\u0000"+ - "\u150d\u150e\u0007\u0006\u0000\u0000\u150e\u0434\u0001\u0000\u0000\u0000"+ - "\u150f\u1510\u0007\u0019\u0000\u0000\u1510\u1511\u0007\u0006\u0000\u0000"+ - "\u1511\u1512\u0007\u0013\u0000\u0000\u1512\u1513\u0007\u0013\u0000\u0000"+ - "\u1513\u1514\u0007\r\u0000\u0000\u1514\u0436\u0001\u0000\u0000\u0000\u1515"+ - "\u1516\u0007\u0017\u0000\u0000\u1516\u1517\u0007\u000e\u0000\u0000\u1517"+ - "\u1518\u0007\f\u0000\u0000\u1518\u0438\u0001\u0000\u0000\u0000\u1519\u151a"+ - "\u0007\u0006\u0000\u0000\u151a\u151b\u0007\u000e\u0000\u0000\u151b\u151c"+ - "\u0007\u000f\u0000\u0000\u151c\u043a\u0001\u0000\u0000\u0000\u151d\u151e"+ - "\u0007\u0006\u0000\u0000\u151e\u151f\u0007\u0007\u0000\u0000\u151f\u043c"+ - "\u0001\u0000\u0000\u0000\u1520\u1521\u0007\u0006\u0000\u0000\u1521\u1522"+ - "\u0007\u0013\u0000\u0000\u1522\u1523\u0007\u0017\u0000\u0000\u1523\u1524"+ - "\u00051\u0000\u0000\u1524\u1525\u00050\u0000\u0000\u1525\u043e\u0001\u0000"+ - "\u0000\u0000\u1526\u1527\u0007\u000f\u0000\u0000\u1527\u1528\u0007\u0011"+ - "\u0000\u0000\u1528\u1529\u0007\u0007\u0000\u0000\u1529\u152a\u0005_\u0000"+ - "\u0000\u152a\u152b\u0007\t\u0000\u0000\u152b\u152c\u0007\u000e\u0000\u0000"+ - "\u152c\u152d\u0007\u0005\u0000\u0000\u152d\u152e\u0007\u0006\u0000\u0000"+ - "\u152e\u152f\u0007\n\u0000\u0000\u152f\u0440\u0001\u0000\u0000\u0000\u1530"+ - "\u1531\u0007\u000f\u0000\u0000\u1531\u1532\u0007\u0013\u0000\u0000\u1532"+ - "\u1533\u0007\f\u0000\u0000\u1533\u0442\u0001\u0000\u0000\u0000\u1534\u1535"+ - "\u0007\u0018\u0000\u0000\u1535\u1536\u0007\u0011\u0000\u0000\u1536\u0444"+ - "\u0001\u0000\u0000\u0000\u1537\u1538\u0007\u0018\u0000\u0000\u1538\u1539"+ - "\u0007\u0013\u0000\u0000\u1539\u153a\u0007\u001d\u0000\u0000\u153a\u153b"+ - "\u0007\n\u0000\u0000\u153b\u153c\u0007\r\u0000\u0000\u153c\u0446\u0001"+ - "\u0000\u0000\u0000\u153d\u153e\u0007\r\u0000\u0000\u153e\u153f\u0007\u0005"+ - "\u0000\u0000\u153f\u1540\u0007\f\u0000\u0000\u1540\u1541\u0007\u0011\u0000"+ - "\u0000\u1541\u1542\u0007\u0005\u0000\u0000\u1542\u1543\u0007\u0007\u0000"+ - "\u0000\u1543\u1544\u0007\t\u0000\u0000\u1544\u0448\u0001\u0000\u0000\u0000"+ - "\u1545\u1546\u0007\r\u0000\u0000\u1546\u1547\u0007\u0013\u0000\u0000\u1547"+ - "\u1548\u0007\u0016\u0000\u0000\u1548\u1549\u0007\u0007\u0000\u0000\u1549"+ - "\u154a\u0007\f\u0000\u0000\u154a\u044a\u0001\u0000\u0000\u0000\u154b\u154c"+ - "\u0007\t\u0000\u0000\u154c\u154d\u0007\u000e\u0000\u0000\u154d\u154e\u0007"+ - "\u0005\u0000\u0000\u154e\u154f\u0007\u0006\u0000\u0000\u154f\u1550\u0007"+ - "\n\u0000\u0000\u1550\u044c\u0001\u0000\u0000\u0000\u1551\u1552\u0007\t"+ - "\u0000\u0000\u1552\u1553\u0007\u0011\u0000\u0000\u1553\u1554\u0007\u0017"+ - "\u0000\u0000\u1554\u1555\u0007\u0007\u0000\u0000\u1555\u044e\u0001\u0000"+ - "\u0000\u0000\u1556\u1557\u0007\t\u0000\u0000\u1557\u1558\u0007\u001c\u0000"+ - "\u0000\u1558\u1559\u0007\r\u0000\u0000\u1559\u155a\u0007\u0010\u0000\u0000"+ - "\u155a\u0450\u0001\u0000\u0000\u0000\u155b\u155c\u0007\u0010\u0000\u0000"+ - "\u155c\u155d\u0007\r\u0000\u0000\u155d\u155e\u0007\u0011\u0000\u0000\u155e"+ - "\u155f\u0007\u000f\u0000\u0000\u155f\u1560\u0005_\u0000\u0000\u1560\u1561"+ - "\u0007\t\u0000\u0000\u1561\u1562\u0007\u000e\u0000\u0000\u1562\u1563\u0007"+ - "\u0005\u0000\u0000\u1563\u1564\u0007\u0006\u0000\u0000\u1564\u1565\u0007"+ - "\n\u0000\u0000\u1565\u0452\u0001\u0000\u0000\u0000\u1566\u1567\u0007\u0010"+ - "\u0000\u0000\u1567\u1568\u0007\r\u0000\u0000\u1568\u1569\u0007\u0016\u0000"+ - "\u0000\u1569\u156a\u0007\u0007\u0000\u0000\u156a\u156b\u0007\u000e\u0000"+ - "\u0000\u156b\u0454\u0001\u0000\u0000\u0000\u156c\u156d\u0007\u001d\u0000"+ - "\u0000\u156d\u156e\u0007\u0011\u0000\u0000\u156e\u156f\u0007\f\u0000\u0000"+ - "\u156f\u1570\u0007\u0010\u0000\u0000\u1570\u1571\u0007\u0014\u0000\u0000"+ - "\u1571\u1572\u0005_\u0000\u0000\u1572\u1573\u0007\u0012\u0000\u0000\u1573"+ - "\u1574\u0007\u0016\u0000\u0000\u1574\u1575\u0007\u000e\u0000\u0000\u1575"+ - "\u1576\u0007\u0015\u0000\u0000\u1576\u1577\u0007\n\u0000\u0000\u1577\u1578"+ - "\u0007\u0010\u0000\u0000\u1578\u0456\u0001\u0000\u0000\u0000\u1579\u157a"+ - "\u0007\r\u0000\u0000\u157a\u157b\u0007\u0005\u0000\u0000\u157b\u157c\u0007"+ - "\u0007\u0000\u0000\u157c\u157d\u0007\f\u0000\u0000\u157d\u157e\u0007\u0013"+ - "\u0000\u0000\u157e\u157f\u0007\u000f\u0000\u0000\u157f\u0458\u0001\u0000"+ - "\u0000\u0000\u1580\u1581\u0007\t\u0000\u0000\u1581\u1582\u0007\n\u0000"+ - "\u0000\u1582\u1583\u0007\u0010\u0000\u0000\u1583\u1584\u0007\t\u0000\u0000"+ - "\u1584\u1585\u0007\n\u0000\u0000\u1585\u1586\u0007\n\u0000\u0000\u1586"+ - "\u1587\u0007\f\u0000\u0000\u1587\u045a\u0001\u0000\u0000\u0000\u1588\u1589"+ - "\u0007\u0005\u0000\u0000\u1589\u158a\u0007\u000e\u0000\u0000\u158a\u158b"+ - "\u0007\u0013\u0000\u0000\u158b\u158c\u0007\t\u0000\u0000\u158c\u045c\u0001"+ - "\u0000\u0000\u0000\u158d\u158e\u0007\u0005\u0000\u0000\u158e\u158f\u0007"+ - "\u000e\u0000\u0000\u158f\u1590\u0007\u0013\u0000\u0000\u1590\u1591\u0007"+ - "\t\u0000\u0000\u1591\u1592\u0007\f\u0000\u0000\u1592\u045e\u0001\u0000"+ - "\u0000\u0000\u1593\u1594\u0007\u0005\u0000\u0000\u1594\u1595\u0007\t\u0000"+ - "\u0000\u1595\u1596\u0007\u0011\u0000\u0000\u1596\u1597\u0007\u0007\u0000"+ - "\u0000\u1597\u0460\u0001\u0000\u0000\u0000\u1598\u1599\u0007\u0005\u0000"+ - "\u0000\u1599\u159a\u0007\t\u0000\u0000\u159a\u159b\u0007\u0011\u0000\u0000"+ - "\u159b\u159c\u0007\u0007\u0000\u0000\u159c\u159d\u0007\f\u0000\u0000\u159d"+ - "\u0462\u0001\u0000\u0000\u0000\u159e\u159f\u0007\u0005\u0000\u0000\u159f"+ - "\u15a0\u0007\u0010\u0000\u0000\u15a0\u15a1\u0007\u0005\u0000\u0000\u15a1"+ - "\u15a2\u0007\u0007\u0000\u0000\u15a2\u0464\u0001\u0000\u0000\u0000\u15a3"+ - "\u15a4\u0007\u0005\u0000\u0000\u15a4\u15a5\u0007\u0010\u0000\u0000\u15a5"+ - "\u15a6\u0007\u0005\u0000\u0000\u15a6\u15a7\u0007\u0007\u0000\u0000\u15a7"+ - "\u15a8\u0007\f\u0000\u0000\u15a8\u0466\u0001\u0000\u0000\u0000\u15a9\u15aa"+ - "\u0007\u0005\u0000\u0000\u15aa\u15ab\u0007\u0010\u0000\u0000\u15ab\u15ac"+ - "\u0007\u0005\u0000\u0000\u15ac\u15ad\u0007\u0007\u0000\u0000\u15ad\u15ae"+ - "\u00052\u0000\u0000\u15ae\u0468\u0001\u0000\u0000\u0000\u15af\u15b0\u0007"+ - "\u0005\u0000\u0000\u15b0\u15b1\u0007\u0010\u0000\u0000\u15b1\u15b2\u0007"+ - "\u0005\u0000\u0000\u15b2\u15b3\u0007\u0007\u0000\u0000\u15b3\u15b4\u0005"+ - "2\u0000\u0000\u15b4\u15b5\u0007\f\u0000\u0000\u15b5\u046a\u0001\u0000"+ - "\u0000\u0000\u15b6\u15b7\u0007\u000e\u0000\u0000\u15b7\u15b8\u0007\u0013"+ - "\u0000\u0000\u15b8\u15b9\u0007\t\u0000\u0000\u15b9\u046c\u0001\u0000\u0000"+ - "\u0000\u15ba\u15bb\u0007\u000e\u0000\u0000\u15bb\u15bc\u0007\u0013\u0000"+ - "\u0000\u15bc\u15bd\u0007\t\u0000\u0000\u15bd\u15be\u0007\f\u0000\u0000"+ - "\u15be\u046e\u0001\u0000\u0000\u0000\u15bf\u15c0\u0007\u000e\u0000\u0000"+ - "\u15c0\u15c1\u0007\u0013\u0000\u0000\u15c1\u15c2\u0007\u0010\u0000\u0000"+ - "\u15c2\u0470\u0001\u0000\u0000\u0000\u15c3\u15c4\u0007\u000e\u0000\u0000"+ - "\u15c4\u15c5\u0007\u0013\u0000\u0000\u15c5\u15c6\u0007\u0010\u0000\u0000"+ - "\u15c6\u15c7\u0007\f\u0000\u0000\u15c7\u0472\u0001\u0000\u0000\u0000\u15c8"+ - "\u15c9\u0007\t\u0000\u0000\u15c9\u15ca\u0007\u0011\u0000\u0000\u15ca\u15cb"+ - "\u0007\u0007\u0000\u0000\u15cb\u0474\u0001\u0000\u0000\u0000\u15cc\u15cd"+ - "\u0007\t\u0000\u0000\u15cd\u15ce\u0007\u0011\u0000\u0000\u15ce\u15cf\u0007"+ - "\u0007\u0000\u0000\u15cf\u15d0\u0007\f\u0000\u0000\u15d0\u0476\u0001\u0000"+ - "\u0000\u0000\u15d1\u15d2\u0007\u0010\u0000\u0000\u15d2\u15d3\u0007\u0005"+ - "\u0000\u0000\u15d3\u15d4\u0007\u0007\u0000\u0000\u15d4\u0478\u0001\u0000"+ - "\u0000\u0000\u15d5\u15d6\u0007\u0010\u0000\u0000\u15d6\u15d7\u0007\u0005"+ - "\u0000\u0000\u15d7\u15d8\u0007\u0007\u0000\u0000\u15d8\u15d9\u0007\f\u0000"+ - "\u0000\u15d9\u047a\u0001\u0000\u0000\u0000\u15da\u15db\u0007\t\u0000\u0000"+ - "\u15db\u15dc\u0007\u0011\u0000\u0000\u15dc\u15dd\u0007\u0007\u0000\u0000"+ - "\u15dd\u15de\u0007\u0014\u0000\u0000\u15de\u047c\u0001\u0000\u0000\u0000"+ - "\u15df\u15e0\u0007\u000e\u0000\u0000\u15e0\u15e1\u0007\u0013\u0000\u0000"+ - "\u15e1\u15e2\u0007\t\u0000\u0000\u15e2\u15e3\u0007\u0014\u0000\u0000\u15e3"+ - "\u047e\u0001\u0000\u0000\u0000\u15e4\u15e5\u0007\u0010\u0000\u0000\u15e5"+ - "\u15e6\u0007\u0005\u0000\u0000\u15e6\u15e7\u0007\u0007\u0000\u0000\u15e7"+ - "\u15e8\u0007\u0014\u0000\u0000\u15e8\u0480\u0001\u0000\u0000\u0000\u15e9"+ - "\u15ea\u0007\u0005\u0000\u0000\u15ea\u15eb\u0007\t\u0000\u0000\u15eb\u15ec"+ - "\u0007\u0011\u0000\u0000\u15ec\u15ed\u0007\u0007\u0000\u0000\u15ed\u15ee"+ - "\u0007\u0014\u0000\u0000\u15ee\u0482\u0001\u0000\u0000\u0000\u15ef\u15f0"+ - "\u0007\u0005\u0000\u0000\u15f0\u15f1\u0007\u000e\u0000\u0000\u15f1\u15f2"+ - "\u0007\u0013\u0000\u0000\u15f2\u15f3\u0007\t\u0000\u0000\u15f3\u15f4\u0007"+ - "\u0014\u0000\u0000\u15f4\u0484\u0001\u0000\u0000\u0000\u15f5\u15f6\u0007"+ - "\u0005\u0000\u0000\u15f6\u15f7\u0007\u0010\u0000\u0000\u15f7\u15f8\u0007"+ - "\u0005\u0000\u0000\u15f8\u15f9\u0007\u0007\u0000\u0000\u15f9\u15fa\u0007"+ - "\u0014\u0000\u0000\u15fa\u0486\u0001\u0000\u0000\u0000\u15fb\u15fc\u0007"+ - "\u0012\u0000\u0000\u15fc\u15fd\u0007\u0011\u0000\u0000\u15fd\u15fe\u0007"+ - "\u0010\u0000\u0000\u15fe\u15ff\u0005_\u0000\u0000\u15ff\u1600\u0007\u0006"+ - "\u0000\u0000\u1600\u1601\u0007\n\u0000\u0000\u1601\u1602\u0007\u0007\u0000"+ - "\u0000\u1602\u1603\u0007\u0017\u0000\u0000\u1603\u1604\u0007\u0010\u0000"+ - "\u0000\u1604\u1605\u0007\u0014\u0000\u0000\u1605\u0488\u0001\u0000\u0000"+ - "\u0000\u1606\u1607\u0007\u000e\u0000\u0000\u1607\u1608\u0007\u0014\u0000"+ - "\u0000\u1608\u1609\u0007\u0005\u0000\u0000\u1609\u160a\u0007\r\u0000\u0000"+ - "\u160a\u160b\u0005_\u0000\u0000\u160b\u160c\u0007\u0006\u0000\u0000\u160c"+ - "\u160d\u0007\n\u0000\u0000\u160d\u160e\u0007\u0007\u0000\u0000\u160e\u160f"+ - "\u0007\u0017\u0000\u0000\u160f\u1610\u0007\u0010\u0000\u0000\u1610\u1611"+ - "\u0007\u0014\u0000\u0000\u1611\u048a\u0001\u0000\u0000\u0000\u1612\u1613"+ - "\u0007\u000e\u0000\u0000\u1613\u1614\u0007\u0014\u0000\u0000\u1614\u1615"+ - "\u0007\u0005\u0000\u0000\u1615\u1616\u0007\r\u0000\u0000\u1616\u1617\u0007"+ - "\u0005\u0000\u0000\u1617\u1618\u0007\u000e\u0000\u0000\u1618\u1619\u0007"+ - "\u0010\u0000\u0000\u1619\u161a\u0007\n\u0000\u0000\u161a\u161b\u0007\r"+ - "\u0000\u0000\u161b\u161c\u0005_\u0000\u0000\u161c\u161d\u0007\u0006\u0000"+ - "\u0000\u161d\u161e\u0007\n\u0000\u0000\u161e\u161f\u0007\u0007\u0000\u0000"+ - "\u161f\u1620\u0007\u0017\u0000\u0000\u1620\u1621\u0007\u0010\u0000\u0000"+ - "\u1621\u1622\u0007\u0014\u0000\u0000\u1622\u048c\u0001\u0000\u0000\u0000"+ - "\u1623\u1624\u0007\u0006\u0000\u0000\u1624\u1625\u0007\u0013\u0000\u0000"+ - "\u1625\u1626\u0007\u001d\u0000\u0000\u1626\u1627\u0007\n\u0000\u0000\u1627"+ - "\u1628\u0007\r\u0000\u0000\u1628\u048e\u0001\u0000\u0000\u0000\u1629\u162a"+ - "\u0007\u0013\u0000\u0000\u162a\u162b\u0007\u000e\u0000\u0000\u162b\u162c"+ - "\u0007\u0010\u0000\u0000\u162c\u162d\u0007\n\u0000\u0000\u162d\u162e\u0007"+ - "\u0010\u0000\u0000\u162e\u162f\u0005_\u0000\u0000\u162f\u1630\u0007\u0006"+ - "\u0000\u0000\u1630\u1631\u0007\n\u0000\u0000\u1631\u1632\u0007\u0007\u0000"+ - "\u0000\u1632\u1633\u0007\u0017\u0000\u0000\u1633\u1634\u0007\u0010\u0000"+ - "\u0000\u1634\u1635\u0007\u0014\u0000\u0000\u1635\u0490\u0001\u0000\u0000"+ - "\u0000\u1636\u1637\u0007\u0016\u0000\u0000\u1637\u1638\u0007\u0018\u0000"+ - "\u0000\u1638\u1639\u0007\u0018\u0000\u0000\u1639\u163a\u0007\n\u0000\u0000"+ - "\u163a\u163b\u0007\r\u0000\u0000\u163b\u0492\u0001\u0000\u0000\u0000\u163c"+ - "\u163d\u0007\u0005\u0000\u0000\u163d\u163e\u0007\t\u0000\u0000\u163e\u163f"+ - "\u0007\u000e\u0000\u0000\u163f\u1640\u0007\u0011\u0000\u0000\u1640\u1641"+ - "\u0007\u0011\u0000\u0000\u1641\u0494\u0001\u0000\u0000\u0000\u1642\u1643"+ - "\u0007\u0012\u0000\u0000\u1643\u1644\u0007\u0010\u0000\u0000\u1644\u1645"+ - "\u0007\r\u0000\u0000\u1645\u1646\u0007\u0011\u0000\u0000\u1646\u1647\u0007"+ - "\u000f\u0000\u0000\u1647\u0496\u0001\u0000\u0000\u0000\u1648\u1649\u0007"+ - "\u000e\u0000\u0000\u1649\u164a\u0007\u0014\u0000\u0000\u164a\u164b\u0007"+ - "\r\u0000\u0000\u164b\u0498\u0001\u0000\u0000\u0000\u164c\u164d\u0007\u000e"+ - "\u0000\u0000\u164d\u164e\u0007\u0013\u0000\u0000\u164e\u164f\u0007\u0007"+ - "\u0000\u0000\u164f\u1650\u0007\u000e\u0000\u0000\u1650\u1651\u0007\u0005"+ - "\u0000\u0000\u1651\u1652\u0007\u0010\u0000\u0000\u1652\u049a\u0001\u0000"+ - "\u0000\u0000\u1653\u1654\u0007\u000e\u0000\u0000\u1654\u1655\u0007\u0013"+ - "\u0000\u0000\u1655\u1656\u0007\u0007\u0000\u0000\u1656\u1657\u0007\u000e"+ - "\u0000\u0000\u1657\u1658\u0007\u0005\u0000\u0000\u1658\u1659\u0007\u0010"+ - "\u0000\u0000\u1659\u165a\u0005_\u0000\u0000\u165a\u165b\u0007\u001d\u0000"+ - "\u0000\u165b\u165c\u0007\t\u0000\u0000\u165c\u049c\u0001\u0000\u0000\u0000"+ - "\u165d\u165e\u0007\u0019\u0000\u0000\u165e\u165f\u0007\u0013\u0000\u0000"+ - "\u165f\u1660\u0007\r\u0000\u0000\u1660\u1661\u0007\u000f\u0000\u0000\u1661"+ - "\u1662\u0007\u0005\u0000\u0000\u1662\u1663\u0007\u0010\u0000\u0000\u1663"+ - "\u049e\u0001\u0000\u0000\u0000\u1664\u1665\u0007\u0011\u0000\u0000\u1665"+ - "\u1666\u0007\u0007\u0000\u0000\u1666\u1667\u0007\u0011\u0000\u0000\u1667"+ - "\u1668\u0007\u0010\u0000\u0000\u1668\u1669\u0007\u000e\u0000\u0000\u1669"+ - "\u166a\u0007\u0005\u0000\u0000\u166a\u166b\u0007\u0018\u0000\u0000\u166b"+ - "\u04a0\u0001\u0000\u0000\u0000\u166c\u166d\u0007\u0006\u0000\u0000\u166d"+ - "\u166e\u0007\n\u0000\u0000\u166e\u166f\u0007\u0007\u0000\u0000\u166f\u1670"+ - "\u0007\u0017\u0000\u0000\u1670\u1671\u0007\u0010\u0000\u0000\u1671\u1672"+ - "\u0007\u0014\u0000\u0000\u1672\u04a2\u0001\u0000\u0000\u0000\u1673\u1674"+ - "\u0007\u0006\u0000\u0000\u1674\u1675\u0007\u0018\u0000\u0000\u1675\u1676"+ - "\u0007\u0005\u0000\u0000\u1676\u1677\u0007\f\u0000\u0000\u1677\u04a4\u0001"+ - "\u0000\u0000\u0000\u1678\u1679\u0007\u0006\u0000\u0000\u1679\u167a\u0007"+ - "\u0010\u0000\u0000\u167a\u167b\u0007\r\u0000\u0000\u167b\u167c\u0007\u0011"+ - "\u0000\u0000\u167c\u167d\u0007\u000f\u0000\u0000\u167d\u04a6\u0001\u0000"+ - "\u0000\u0000\u167e\u167f\u0007\u000f\u0000\u0000\u167f\u1680\u0007\f\u0000"+ - "\u0000\u1680\u1681\u00055\u0000\u0000\u1681\u04a8\u0001\u0000\u0000\u0000"+ - "\u1682\u1683\u0007\u0018\u0000\u0000\u1683\u1684\u0007\u0005\u0000\u0000"+ - "\u1684\u1685\u0007\r\u0000\u0000\u1685\u1686\u0007\t\u0000\u0000\u1686"+ - "\u1687\u0007\n\u0000\u0000\u1687\u1688\u0005_\u0000\u0000\u1688\u1689"+ - "\u0007\u0011\u0000\u0000\u1689\u168a\u0007\f\u0000\u0000\u168a\u168b\u0007"+ - "\n\u0000\u0000\u168b\u168c\u0007\u0007\u0000\u0000\u168c\u168d\u0007\u0010"+ - "\u0000\u0000\u168d\u04aa\u0001\u0000\u0000\u0000\u168e\u168f\u0007\u0018"+ - "\u0000\u0000\u168f\u1690\u0007\u0017\u0000\u0000\u1690\u1691\u0005_\u0000"+ - "\u0000\u1691\u1692\u0007\u000e\u0000\u0000\u1692\u1693\u0007\u0006\u0000"+ - "\u0000\u1693\u1694\u0007\u0011\u0000\u0000\u1694\u1695\u0007\n\u0000\u0000"+ - "\u1695\u1696\u0007\u0007\u0000\u0000\u1696\u1697\u0007\u0010\u0000\u0000"+ - "\u1697\u1698\u0005_\u0000\u0000\u1698\u1699\u0007\n\u0000\u0000\u1699"+ - "\u169a\u0007\u0007\u0000\u0000\u169a\u169b\u0007\u000e\u0000\u0000\u169b"+ - "\u169c\u0007\u0013\u0000\u0000\u169c\u169d\u0007\f\u0000\u0000\u169d\u169e"+ - "\u0007\u0011\u0000\u0000\u169e\u169f\u0007\u0007\u0000\u0000\u169f\u16a0"+ - "\u0007\u0017\u0000\u0000\u16a0\u04ac\u0001\u0000\u0000\u0000\u16a1\u16a2"+ - "\u0007\u001c\u0000\u0000\u16a2\u16a3\u0007\u0016\u0000\u0000\u16a3\u16a4"+ - "\u0007\u0013\u0000\u0000\u16a4\u16a5\u0007\u0010\u0000\u0000\u16a5\u16a6"+ - "\u0007\n\u0000\u0000\u16a6\u16a7\u0005_\u0000\u0000\u16a7\u16a8\u0007"+ - "\u0011\u0000\u0000\u16a8\u16a9\u0007\f\u0000\u0000\u16a9\u16aa\u0007\n"+ - "\u0000\u0000\u16aa\u16ab\u0007\u0007\u0000\u0000\u16ab\u16ac\u0007\u0010"+ - "\u0000\u0000\u16ac\u04ae\u0001\u0000\u0000\u0000\u16ad\u16ae\u0007\u001c"+ - "\u0000\u0000\u16ae\u16af\u0007\u0016\u0000\u0000\u16af\u16b0\u0007\u0013"+ - "\u0000\u0000\u16b0\u16b1\u0007\u0010\u0000\u0000\u16b1\u16b2\u0007\n\u0000"+ - "\u0000\u16b2\u16b3\u0005_\u0000\u0000\u16b3\u16b4\u0007\u0006\u0000\u0000"+ - "\u16b4\u16b5\u0007\u0011\u0000\u0000\u16b5\u16b6\u0007\u0010\u0000\u0000"+ - "\u16b6\u16b7\u0007\n\u0000\u0000\u16b7\u16b8\u0007\r\u0000\u0000\u16b8"+ - "\u16b9\u0007\u0005\u0000\u0000\u16b9\u16ba\u0007\u0006\u0000\u0000\u16ba"+ - "\u04b0\u0001\u0000\u0000\u0000\u16bb\u16bc\u0007\u001c\u0000\u0000\u16bc"+ - "\u16bd\u0007\u0016\u0000\u0000\u16bd\u16be\u0007\u0013\u0000\u0000\u16be"+ - "\u16bf\u0007\u0010\u0000\u0000\u16bf\u16c0\u0007\n\u0000\u0000\u16c0\u16c1"+ - "\u0005_\u0000\u0000\u16c1\u16c2\u0007\u0007\u0000\u0000\u16c2\u16c3\u0007"+ - "\u0016\u0000\u0000\u16c3\u16c4\u0007\u0006\u0000\u0000\u16c4\u16c5\u0007"+ - "\u0006\u0000\u0000\u16c5\u16c6\u0007\u0005\u0000\u0000\u16c6\u16c7\u0007"+ - "\u0012\u0000\u0000\u16c7\u16c8\u0007\u0006\u0000\u0000\u16c8\u16c9\u0007"+ - "\n\u0000\u0000\u16c9\u04b2\u0001\u0000\u0000\u0000\u16ca\u16cb\u0007\r"+ - "\u0000\u0000\u16cb\u16cc\u0007\n\u0000\u0000\u16cc\u16cd\u0007\u0017\u0000"+ - "\u0000\u16cd\u16ce\u0007\n\u0000\u0000\u16ce\u16cf\u0007\u001a\u0000\u0000"+ - "\u16cf\u16d0\u0007\u0018\u0000\u0000\u16d0\u16d1\u0005_\u0000\u0000\u16d1"+ - "\u16d2\u0007\u000e\u0000\u0000\u16d2\u16d3\u0007\u0013\u0000\u0000\u16d3"+ - "\u16d4\u0007\u0016\u0000\u0000\u16d4\u16d5\u0007\u0007\u0000\u0000\u16d5"+ - "\u16d6\u0007\u0010\u0000\u0000\u16d6\u04b4\u0001\u0000\u0000\u0000\u16d7"+ - "\u16d8\u0007\r\u0000\u0000\u16d8\u16d9\u0007\n\u0000\u0000\u16d9\u16da"+ - "\u0007\u0017\u0000\u0000\u16da\u16db\u0007\n\u0000\u0000\u16db\u16dc\u0007"+ - "\u001a\u0000\u0000\u16dc\u16dd\u0007\u0018\u0000\u0000\u16dd\u16de\u0005"+ - "_\u0000\u0000\u16de\u16df\u0007\u0011\u0000\u0000\u16df\u16e0\u0007\u0007"+ - "\u0000\u0000\u16e0\u16e1\u0007\t\u0000\u0000\u16e1\u16e2\u0007\u0010\u0000"+ - "\u0000\u16e2\u16e3\u0007\r\u0000\u0000\u16e3\u04b6\u0001\u0000\u0000\u0000"+ - "\u16e4\u16e5\u0007\r\u0000\u0000\u16e5\u16e6\u0007\n\u0000\u0000\u16e6"+ - "\u16e7\u0007\u0017\u0000\u0000\u16e7\u16e8\u0007\n\u0000\u0000\u16e8\u16e9"+ - "\u0007\u001a\u0000\u0000\u16e9\u16ea\u0007\u0018\u0000\u0000\u16ea\u16eb"+ - "\u0005_\u0000\u0000\u16eb\u16ec\u0007\u0006\u0000\u0000\u16ec\u16ed\u0007"+ - "\u0011\u0000\u0000\u16ed\u16ee\u0007\u0015\u0000\u0000\u16ee\u16ef\u0007"+ - "\n\u0000\u0000\u16ef\u04b8\u0001\u0000\u0000\u0000\u16f0\u16f1\u0007\r"+ - "\u0000\u0000\u16f1\u16f2\u0007\n\u0000\u0000\u16f2\u16f3\u0007\u0017\u0000"+ - "\u0000\u16f3\u16f4\u0007\n\u0000\u0000\u16f4\u16f5\u0007\u001a\u0000\u0000"+ - "\u16f5\u16f6\u0007\u0018\u0000\u0000\u16f6\u16f7\u0005_\u0000\u0000\u16f7"+ - "\u16f8\u0007\u000f\u0000\u0000\u16f8\u16f9\u0007\u0005\u0000\u0000\u16f9"+ - "\u16fa\u0007\u0010\u0000\u0000\u16fa\u16fb\u0007\u000e\u0000\u0000\u16fb"+ - "\u16fc\u0007\u0014\u0000\u0000\u16fc\u04ba\u0001\u0000\u0000\u0000\u16fd"+ - "\u16fe\u0007\r\u0000\u0000\u16fe\u16ff\u0007\n\u0000\u0000\u16ff\u1700"+ - "\u0007\u0017\u0000\u0000\u1700\u1701\u0007\n\u0000\u0000\u1701\u1702\u0007"+ - "\u001a\u0000\u0000\u1702\u1703\u0007\u0018\u0000\u0000\u1703\u1704\u0005"+ - "_\u0000\u0000\u1704\u1705\u0007\u000f\u0000\u0000\u1705\u1706\u0007\u0005"+ - "\u0000\u0000\u1706\u1707\u0007\u0010\u0000\u0000\u1707\u1708\u0007\u000e"+ - "\u0000\u0000\u1708\u1709\u0007\u0014\u0000\u0000\u1709\u170a\u0007\n\u0000"+ - "\u0000\u170a\u170b\u0007\t\u0000\u0000\u170b\u04bc\u0001\u0000\u0000\u0000"+ - "\u170c\u170d\u0007\r\u0000\u0000\u170d\u170e\u0007\n\u0000\u0000\u170e"+ - "\u170f\u0007\u0017\u0000\u0000\u170f\u1710\u0007\n\u0000\u0000\u1710\u1711"+ - "\u0007\u001a\u0000\u0000\u1711\u1712\u0007\u0018\u0000\u0000\u1712\u1713"+ - "\u0005_\u0000\u0000\u1713\u1714\u0007\r\u0000\u0000\u1714\u1715\u0007"+ - "\n\u0000\u0000\u1715\u1716\u0007\u0018\u0000\u0000\u1716\u1717\u0007\u0006"+ - "\u0000\u0000\u1717\u1718\u0007\u0005\u0000\u0000\u1718\u1719\u0007\u000e"+ - "\u0000\u0000\u1719\u171a\u0007\n\u0000\u0000\u171a\u04be\u0001\u0000\u0000"+ - "\u0000\u171b\u171c\u0007\r\u0000\u0000\u171c\u171d\u0007\n\u0000\u0000"+ - "\u171d\u171e\u0007\u0017\u0000\u0000\u171e\u171f\u0007\n\u0000\u0000\u171f"+ - "\u1720\u0007\u001a\u0000\u0000\u1720\u1721\u0007\u0018\u0000\u0000\u1721"+ - "\u1722\u0005_\u0000\u0000\u1722\u1723\u0007\t\u0000\u0000\u1723\u1724"+ - "\u0007\u0018\u0000\u0000\u1724\u1725\u0007\u0006\u0000\u0000\u1725\u1726"+ - "\u0007\u0011\u0000\u0000\u1726\u1727\u0007\u0010\u0000\u0000\u1727\u1728"+ - "\u0005_\u0000\u0000\u1728\u1729\u0007\u0010\u0000\u0000\u1729\u172a\u0007"+ - "\u0013\u0000\u0000\u172a\u172b\u0005_\u0000\u0000\u172b\u172c\u0007\u0005"+ - "\u0000\u0000\u172c\u172d\u0007\r\u0000\u0000\u172d\u172e\u0007\r\u0000"+ - "\u0000\u172e\u172f\u0007\u0005\u0000\u0000\u172f\u1730\u0007\b\u0000\u0000"+ - "\u1730\u04c0\u0001\u0000\u0000\u0000\u1731\u1732\u0007\r\u0000\u0000\u1732"+ - "\u1733\u0007\n\u0000\u0000\u1733\u1734\u0007\u0017\u0000\u0000\u1734\u1735"+ - "\u0007\n\u0000\u0000\u1735\u1736\u0007\u001a\u0000\u0000\u1736\u1737\u0007"+ - "\u0018\u0000\u0000\u1737\u1738\u0005_\u0000\u0000\u1738\u1739\u0007\t"+ - "\u0000\u0000\u1739\u173a\u0007\u0018\u0000\u0000\u173a\u173b\u0007\u0006"+ - "\u0000\u0000\u173b\u173c\u0007\u0011\u0000\u0000\u173c\u173d\u0007\u0010"+ - "\u0000\u0000\u173d\u173e\u0005_\u0000\u0000\u173e\u173f\u0007\u0010\u0000"+ - "\u0000\u173f\u1740\u0007\u0013\u0000\u0000\u1740\u1741\u0005_\u0000\u0000"+ - "\u1741\u1742\u0007\u0010\u0000\u0000\u1742\u1743\u0007\u0005\u0000\u0000"+ - "\u1743\u1744\u0007\u0012\u0000\u0000\u1744\u1745\u0007\u0006\u0000\u0000"+ - "\u1745\u1746\u0007\n\u0000\u0000\u1746\u04c2\u0001\u0000\u0000\u0000\u1747"+ - "\u1748\u0007\r\u0000\u0000\u1748\u1749\u0007\n\u0000\u0000\u1749\u174a"+ - "\u0007\u0017\u0000\u0000\u174a\u174b\u0007\n\u0000\u0000\u174b\u174c\u0007"+ - "\u001a\u0000\u0000\u174c\u174d\u0007\u0018\u0000\u0000\u174d\u174e\u0005"+ - "_\u0000\u0000\u174e\u174f\u0007\t\u0000\u0000\u174f\u1750\u0007\u0016"+ - "\u0000\u0000\u1750\u1751\u0007\u0012\u0000\u0000\u1751\u1752\u0007\t\u0000"+ - "\u0000\u1752\u1753\u0007\u0010\u0000\u0000\u1753\u1754\u0007\r\u0000\u0000"+ - "\u1754\u04c4\u0001\u0000\u0000\u0000\u1755\u1756\u0007\r\u0000\u0000\u1756"+ - "\u1757\u0007\n\u0000\u0000\u1757\u1758\u0007\u0018\u0000\u0000\u1758\u1759"+ - "\u0007\n\u0000\u0000\u1759\u175a\u0007\u0005\u0000\u0000\u175a\u175b\u0007"+ - "\u0010\u0000\u0000\u175b\u04c6\u0001\u0000\u0000\u0000\u175c\u175d\u0007"+ - "\r\u0000\u0000\u175d\u175e\u0007\u0018\u0000\u0000\u175e\u175f\u0007\u0005"+ - "\u0000\u0000\u175f\u1760\u0007\f\u0000\u0000\u1760\u04c8\u0001\u0000\u0000"+ - "\u0000\u1761\u1762\u0007\r\u0000\u0000\u1762\u1763\u0007\u0010\u0000\u0000"+ - "\u1763\u1764\u0007\r\u0000\u0000\u1764\u1765\u0007\u0011\u0000\u0000\u1765"+ - "\u1766\u0007\u000f\u0000\u0000\u1766\u04ca\u0001\u0000\u0000\u0000\u1767"+ - "\u1768\u0007\t\u0000\u0000\u1768\u1769\u0007\u0018\u0000\u0000\u1769\u176a"+ - "\u0007\u0006\u0000\u0000\u176a\u176b\u0007\u0011\u0000\u0000\u176b\u176c"+ - "\u0007\u0010\u0000\u0000\u176c\u176d\u0005_\u0000\u0000\u176d\u176e\u0007"+ - "\u0018\u0000\u0000\u176e\u176f\u0007\u0005\u0000\u0000\u176f\u1770\u0007"+ - "\r\u0000\u0000\u1770\u1771\u0007\u0010\u0000\u0000\u1771\u04cc\u0001\u0000"+ - "\u0000\u0000\u1772\u1773\u0007\t\u0000\u0000\u1773\u1774\u0007\u0010\u0000"+ - "\u0000\u1774\u1775\u0007\u0005\u0000\u0000\u1775\u1776\u0007\r\u0000\u0000"+ - "\u1776\u1777\u0007\u0010\u0000\u0000\u1777\u1778\u0007\t\u0000\u0000\u1778"+ - "\u1779\u0005_\u0000\u0000\u1779\u177a\u0007\u001d\u0000\u0000\u177a\u177b"+ - "\u0007\u0011\u0000\u0000\u177b\u177c\u0007\u0010\u0000\u0000\u177c\u177d"+ - "\u0007\u0014\u0000\u0000\u177d\u04ce\u0001\u0000\u0000\u0000\u177e\u177f"+ - "\u0007\t\u0000\u0000\u177f\u1780\u0007\u0010\u0000\u0000\u1780\u1781\u0007"+ - "\r\u0000\u0000\u1781\u1782\u0007\u0011\u0000\u0000\u1782\u1783\u0007\u0007"+ - "\u0000\u0000\u1783\u1784\u0007\u0017\u0000\u0000\u1784\u1785\u0005_\u0000"+ - "\u0000\u1785\u1786\u0007\u0010\u0000\u0000\u1786\u1787\u0007\u0013\u0000"+ - "\u0000\u1787\u1788\u0005_\u0000\u0000\u1788\u1789\u0007\u0005\u0000\u0000"+ - "\u1789\u178a\u0007\r\u0000\u0000\u178a\u178b\u0007\r\u0000\u0000\u178b"+ - "\u178c\u0007\u0005\u0000\u0000\u178c\u178d\u0007\b\u0000\u0000\u178d\u04d0"+ - "\u0001\u0000\u0000\u0000\u178e\u178f\u0007\t\u0000\u0000\u178f\u1790\u0007"+ - "\u0010\u0000\u0000\u1790\u1791\u0007\r\u0000\u0000\u1791\u1792\u0007\u0011"+ - "\u0000\u0000\u1792\u1793\u0007\u0007\u0000\u0000\u1793\u1794\u0007\u0017"+ - "\u0000\u0000\u1794\u1795\u0005_\u0000\u0000\u1795\u1796\u0007\u0010\u0000"+ - "\u0000\u1796\u1797\u0007\u0013\u0000\u0000\u1797\u1798\u0005_\u0000\u0000"+ - "\u1798\u1799\u0007\u0010\u0000\u0000\u1799\u179a\u0007\u0005\u0000\u0000"+ - "\u179a\u179b\u0007\u0012\u0000\u0000\u179b\u179c\u0007\u0006\u0000\u0000"+ - "\u179c\u179d\u0007\n\u0000\u0000\u179d\u04d2\u0001\u0000\u0000\u0000\u179e"+ - "\u179f\u0007\t\u0000\u0000\u179f\u17a0\u0007\u0010\u0000\u0000\u17a0\u17a1"+ - "\u0007\r\u0000\u0000\u17a1\u17a2\u0007\u0018\u0000\u0000\u17a2\u17a3\u0007"+ - "\u0013\u0000\u0000\u17a3\u17a4\u0007\t\u0000\u0000\u17a4\u04d4\u0001\u0000"+ - "\u0000\u0000\u17a5\u17a6\u0007\t\u0000\u0000\u17a6\u17a7\u0007\u0016\u0000"+ - "\u0000\u17a7\u17a8\u0007\u0012\u0000\u0000\u17a8\u17a9\u0007\t\u0000\u0000"+ - "\u17a9\u17aa\u0007\u0010\u0000\u0000\u17aa\u17ab\u0007\r\u0000\u0000\u17ab"+ - "\u04d6\u0001\u0000\u0000\u0000\u17ac\u17ad\u0007\u0010\u0000\u0000\u17ad"+ - "\u17ae\u0007\u0013\u0000\u0000\u17ae\u17af\u0005_\u0000\u0000\u17af\u17b0"+ - "\u0007\u0005\u0000\u0000\u17b0\u17b1\u0007\t\u0000\u0000\u17b1\u17b2\u0007"+ - "\u000e\u0000\u0000\u17b2\u17b3\u0007\u0011\u0000\u0000\u17b3\u17b4\u0007"+ - "\u0011\u0000\u0000\u17b4\u04d8\u0001\u0000\u0000\u0000\u17b5\u17b6\u0007"+ - "\u0010\u0000\u0000\u17b6\u17b7\u0007\u0013\u0000\u0000\u17b7\u17b8\u0005"+ - "_\u0000\u0000\u17b8\u17b9\u0007\u0014\u0000\u0000\u17b9\u17ba\u0007\n"+ - "\u0000\u0000\u17ba\u17bb\u0007\u001a\u0000\u0000\u17bb\u04da\u0001\u0000"+ - "\u0000\u0000\u17bc\u17bd\u0007\u0010\u0000\u0000\u17bd\u17be\u0007\r\u0000"+ - "\u0000\u17be\u17bf\u0007\u0005\u0000\u0000\u17bf\u17c0\u0007\u0007\u0000"+ - "\u0000\u17c0\u17c1\u0007\t\u0000\u0000\u17c1\u17c2\u0007\u0006\u0000\u0000"+ - "\u17c2\u17c3\u0007\u0005\u0000\u0000\u17c3\u17c4\u0007\u0010\u0000\u0000"+ - "\u17c4\u17c5\u0007\n\u0000\u0000\u17c5\u04dc\u0001\u0000\u0000\u0000\u17c6"+ - "\u17c7\u0007\u0016\u0000\u0000\u17c7\u17c8\u0007\u0007\u0000\u0000\u17c8"+ - "\u17c9\u0007\u0011\u0000\u0000\u17c9\u17ca\u0007\t\u0000\u0000\u17ca\u17cb"+ - "\u0007\u0010\u0000\u0000\u17cb\u17cc\u0007\r\u0000\u0000\u17cc\u04de\u0001"+ - "\u0000\u0000\u0000\u17cd\u17ce\u0007\u0005\u0000\u0000\u17ce\u17cf\u0007"+ - "\u0017\u0000\u0000\u17cf\u17d0\u0007\n\u0000\u0000\u17d0\u04e0\u0001\u0000"+ - "\u0000\u0000\u17d1\u17d2\u0007\u000e\u0000\u0000\u17d2\u17d3\u0007\u0006"+ - "\u0000\u0000\u17d3\u17d4\u0007\u0013\u0000\u0000\u17d4\u17d5\u0007\u000e"+ - "\u0000\u0000\u17d5\u17d6\u0007\u0015\u0000\u0000\u17d6\u17d7\u0005_\u0000"+ - "\u0000\u17d7\u17d8\u0007\u0010\u0000\u0000\u17d8\u17d9\u0007\u0011\u0000"+ - "\u0000\u17d9\u17da\u0007\u000f\u0000\u0000\u17da\u17db\u0007\n\u0000\u0000"+ - "\u17db\u17dc\u0007\t\u0000\u0000\u17dc\u17dd\u0007\u0010\u0000\u0000\u17dd"+ - "\u17de\u0007\u0005\u0000\u0000\u17de\u17df\u0007\u000f\u0000\u0000\u17df"+ - "\u17e0\u0007\u0018\u0000\u0000\u17e0\u04e2\u0001\u0000\u0000\u0000\u17e1"+ - "\u17e2\u0007\f\u0000\u0000\u17e2\u17e3\u0007\u0005\u0000\u0000\u17e3\u17e4"+ - "\u0007\u0010\u0000\u0000\u17e4\u17e5\u0007\n\u0000\u0000\u17e5\u17e6\u0005"+ - "_\u0000\u0000\u17e6\u17e7\u0007\u0012\u0000\u0000\u17e7\u17e8\u0007\u0011"+ - "\u0000\u0000\u17e8\u17e9\u0007\u0007\u0000\u0000\u17e9\u04e4\u0001\u0000"+ - "\u0000\u0000\u17ea\u17eb\u0007\f\u0000\u0000\u17eb\u17ec\u0007\u0005\u0000"+ - "\u0000\u17ec\u17ed\u0007\u0010\u0000\u0000\u17ed\u17ee\u0007\n\u0000\u0000"+ - "\u17ee\u17ef\u0005_\u0000\u0000\u17ef\u17f0\u0007\u0018\u0000\u0000\u17f0"+ - "\u17f1\u0007\u0005\u0000\u0000\u17f1\u17f2\u0007\r\u0000\u0000\u17f2\u17f3"+ - "\u0007\u0010\u0000\u0000\u17f3\u04e6\u0001\u0000\u0000\u0000\u17f4\u17f5"+ - "\u0007\f\u0000\u0000\u17f5\u17f6\u0007\u0005\u0000\u0000\u17f6\u17f7\u0007"+ - "\u0010\u0000\u0000\u17f7\u17f8\u0007\n\u0000\u0000\u17f8\u17f9\u0005_"+ - "\u0000\u0000\u17f9\u17fa\u0007\u0010\u0000\u0000\u17fa\u17fb\u0007\r\u0000"+ - "\u0000\u17fb\u17fc\u0007\u0016\u0000\u0000\u17fc\u17fd\u0007\u0007\u0000"+ - "\u0000\u17fd\u17fe\u0007\u000e\u0000\u0000\u17fe\u04e8\u0001\u0000\u0000"+ - "\u0000\u17ff\u1800\u0007\u0011\u0000\u0000\u1800\u1801\u0007\t\u0000\u0000"+ - "\u1801\u1802\u0007\u0019\u0000\u0000\u1802\u1803\u0007\u0011\u0000\u0000"+ - "\u1803\u1804\u0007\u0007\u0000\u0000\u1804\u1805\u0007\u0011\u0000\u0000"+ - "\u1805\u1806\u0007\u0010\u0000\u0000\u1806\u1807\u0007\n\u0000\u0000\u1807"+ - "\u04ea\u0001\u0000\u0000\u0000\u1808\u1809\u0007\u001e\u0000\u0000\u1809"+ - "\u180a\u0007\u0016\u0000\u0000\u180a\u180b\u0007\t\u0000\u0000\u180b\u180c"+ - "\u0007\u0010\u0000\u0000\u180c\u180d\u0007\u0011\u0000\u0000\u180d\u180e"+ - "\u0007\u0019\u0000\u0000\u180e\u180f\u0007\b\u0000\u0000\u180f\u1810\u0005"+ - "_\u0000\u0000\u1810\u1811\u0007\f\u0000\u0000\u1811\u1812\u0007\u0005"+ - "\u0000\u0000\u1812\u1813\u0007\b\u0000\u0000\u1813\u1814\u0007\t\u0000"+ - "\u0000\u1814\u04ec\u0001\u0000\u0000\u0000\u1815\u1816\u0007\u001e\u0000"+ - "\u0000\u1816\u1817\u0007\u0016\u0000\u0000\u1817\u1818\u0007\t\u0000\u0000"+ - "\u1818\u1819\u0007\u0010\u0000\u0000\u1819\u181a\u0007\u0011\u0000\u0000"+ - "\u181a\u181b\u0007\u0019\u0000\u0000\u181b\u181c\u0007\b\u0000\u0000\u181c"+ - "\u181d\u0005_\u0000\u0000\u181d\u181e\u0007\u0014\u0000\u0000\u181e\u181f"+ - "\u0007\u0013\u0000\u0000\u181f\u1820\u0007\u0016\u0000\u0000\u1820\u1821"+ - "\u0007\r\u0000\u0000\u1821\u1822\u0007\t\u0000\u0000\u1822\u04ee\u0001"+ - "\u0000\u0000\u0000\u1823\u1824\u0007\u001e\u0000\u0000\u1824\u1825\u0007"+ - "\u0016\u0000\u0000\u1825\u1826\u0007\t\u0000\u0000\u1826\u1827\u0007\u0010"+ - "\u0000\u0000\u1827\u1828\u0007\u0011\u0000\u0000\u1828\u1829\u0007\u0019"+ - "\u0000\u0000\u1829\u182a\u0007\b\u0000\u0000\u182a\u182b\u0005_\u0000"+ - "\u0000\u182b\u182c\u0007\u0011\u0000\u0000\u182c\u182d\u0007\u0007\u0000"+ - "\u0000\u182d\u182e\u0007\u0010\u0000\u0000\u182e\u182f\u0007\n\u0000\u0000"+ - "\u182f\u1830\u0007\r\u0000\u0000\u1830\u1831\u0007\u001b\u0000\u0000\u1831"+ - "\u1832\u0007\u0005\u0000\u0000\u1832\u1833\u0007\u0006\u0000\u0000\u1833"+ - "\u04f0\u0001\u0000\u0000\u0000\u1834\u1835\u0007\u000f\u0000\u0000\u1835"+ - "\u1836\u0007\u0005\u0000\u0000\u1836\u1837\u0007\u0015\u0000\u0000\u1837"+ - "\u1838\u0007\n\u0000\u0000\u1838\u1839\u0005_\u0000\u0000\u1839\u183a"+ - "\u0007\f\u0000\u0000\u183a\u183b\u0007\u0005\u0000\u0000\u183b\u183c\u0007"+ - "\u0010\u0000\u0000\u183c\u183d\u0007\n\u0000\u0000\u183d\u04f2\u0001\u0000"+ - "\u0000\u0000\u183e\u183f\u0007\u000f\u0000\u0000\u183f\u1840\u0007\u0005"+ - "\u0000\u0000\u1840\u1841\u0007\u0015\u0000\u0000\u1841\u1842\u0007\n\u0000"+ - "\u0000\u1842\u1843\u0005_\u0000\u0000\u1843\u1844\u0007\u0011\u0000\u0000"+ - "\u1844\u1845\u0007\u0007\u0000\u0000\u1845\u1846\u0007\u0010\u0000\u0000"+ - "\u1846\u1847\u0007\n\u0000\u0000\u1847\u1848\u0007\r\u0000\u0000\u1848"+ - "\u1849\u0007\u001b\u0000\u0000\u1849\u184a\u0007\u0005\u0000\u0000\u184a"+ - "\u184b\u0007\u0006\u0000\u0000\u184b\u04f4\u0001\u0000\u0000\u0000\u184c"+ - "\u184d\u0007\u000f\u0000\u0000\u184d\u184e\u0007\u0005\u0000\u0000\u184e"+ - "\u184f\u0007\u0015\u0000\u0000\u184f\u1850\u0007\n\u0000\u0000\u1850\u1851"+ - "\u0005_\u0000\u0000\u1851\u1852\u0007\u0010\u0000\u0000\u1852\u1853\u0007"+ - "\u0011\u0000\u0000\u1853\u1854\u0007\u000f\u0000\u0000\u1854\u1855\u0007"+ - "\n\u0000\u0000\u1855\u04f6\u0001\u0000\u0000\u0000\u1856\u1857\u0007\u000f"+ - "\u0000\u0000\u1857\u1858\u0007\u0005\u0000\u0000\u1858\u1859\u0007\u0015"+ - "\u0000\u0000\u1859\u185a\u0007\n\u0000\u0000\u185a\u185b\u0005_\u0000"+ - "\u0000\u185b\u185c\u0007\u0010\u0000\u0000\u185c\u185d\u0007\u0011\u0000"+ - "\u0000\u185d\u185e\u0007\u000f\u0000\u0000\u185e\u185f\u0007\n\u0000\u0000"+ - "\u185f\u1860\u0007\t\u0000\u0000\u1860\u1861\u0007\u0010\u0000\u0000\u1861"+ - "\u1862\u0007\u0005\u0000\u0000\u1862\u1863\u0007\u000f\u0000\u0000\u1863"+ - "\u1864\u0007\u0018\u0000\u0000\u1864\u04f8\u0001\u0000\u0000\u0000\u1865"+ - "\u1866\u0007\u000f\u0000\u0000\u1866\u1867\u0007\u0005\u0000\u0000\u1867"+ - "\u1868\u0007\u0015\u0000\u0000\u1868\u1869\u0007\n\u0000\u0000\u1869\u186a"+ - "\u0005_\u0000\u0000\u186a\u186b\u0007\u0010\u0000\u0000\u186b\u186c\u0007"+ - "\u0011\u0000\u0000\u186c\u186d\u0007\u000f\u0000\u0000\u186d\u186e\u0007"+ - "\n\u0000\u0000\u186e\u186f\u0007\t\u0000\u0000\u186f\u1870\u0007\u0010"+ - "\u0000\u0000\u1870\u1871\u0007\u0005\u0000\u0000\u1871\u1872\u0007\u000f"+ - "\u0000\u0000\u1872\u1873\u0007\u0018\u0000\u0000\u1873\u1874\u0007\u0010"+ - "\u0000\u0000\u1874\u1875\u0007\u000b\u0000\u0000\u1875\u04fa\u0001\u0000"+ - "\u0000\u0000\u1876\u1877\u0007\u0007\u0000\u0000\u1877\u1878\u0007\u0013"+ - "\u0000\u0000\u1878\u1879\u0007\u001d\u0000\u0000\u1879\u04fc\u0001\u0000"+ - "\u0000\u0000\u187a\u187b\u0007\t\u0000\u0000\u187b\u187c\u0007\u0010\u0000"+ - "\u0000\u187c\u187d\u0007\u0005\u0000\u0000\u187d\u187e\u0007\u0010\u0000"+ - "\u0000\u187e\u187f\u0007\n\u0000\u0000\u187f\u1880\u0007\u000f\u0000\u0000"+ - "\u1880\u1881\u0007\n\u0000\u0000\u1881\u1882\u0007\u0007\u0000\u0000\u1882"+ - "\u1883\u0007\u0010\u0000\u0000\u1883\u1884\u0005_\u0000\u0000\u1884\u1885"+ - "\u0007\u0010\u0000\u0000\u1885\u1886\u0007\u0011\u0000\u0000\u1886\u1887"+ - "\u0007\u000f\u0000\u0000\u1887\u1888\u0007\n\u0000\u0000\u1888\u1889\u0007"+ - "\t\u0000\u0000\u1889\u188a\u0007\u0010\u0000\u0000\u188a\u188b\u0007\u0005"+ - "\u0000\u0000\u188b\u188c\u0007\u000f\u0000\u0000\u188c\u188d\u0007\u0018"+ - "\u0000\u0000\u188d\u04fe\u0001\u0000\u0000\u0000\u188e\u188f\u0007\u0010"+ - "\u0000\u0000\u188f\u1890\u0007\u0011\u0000\u0000\u1890\u1891\u0007\u000f"+ - "\u0000\u0000\u1891\u1892\u0007\n\u0000\u0000\u1892\u1893\u0007\u0013\u0000"+ - "\u0000\u1893\u1894\u0007\u0019\u0000\u0000\u1894\u1895\u0007\f\u0000\u0000"+ - "\u1895\u1896\u0007\u0005\u0000\u0000\u1896\u1897\u0007\b\u0000\u0000\u1897"+ - "\u0500\u0001\u0000\u0000\u0000\u1898\u1899\u0007\u0010\u0000\u0000\u1899"+ - "\u189a\u0007\r\u0000\u0000\u189a\u189b\u0007\u0005\u0000\u0000\u189b\u189c"+ - "\u0007\u0007\u0000\u0000\u189c\u189d\u0007\t\u0000\u0000\u189d\u189e\u0007"+ - "\u0005\u0000\u0000\u189e\u189f\u0007\u000e\u0000\u0000\u189f\u18a0\u0007"+ - "\u0010\u0000\u0000\u18a0\u18a1\u0007\u0011\u0000\u0000\u18a1\u18a2\u0007"+ - "\u0013\u0000\u0000\u18a2\u18a3\u0007\u0007\u0000\u0000\u18a3\u18a4\u0005"+ - "_\u0000\u0000\u18a4\u18a5\u0007\u0010\u0000\u0000\u18a5\u18a6\u0007\u0011"+ - "\u0000\u0000\u18a6\u18a7\u0007\u000f\u0000\u0000\u18a7\u18a8\u0007\n\u0000"+ - "\u0000\u18a8\u18a9\u0007\t\u0000\u0000\u18a9\u18aa\u0007\u0010\u0000\u0000"+ - "\u18aa\u18ab\u0007\u0005\u0000\u0000\u18ab\u18ac\u0007\u000f\u0000\u0000"+ - "\u18ac\u18ad\u0007\u0018\u0000\u0000\u18ad\u0502\u0001\u0000\u0000\u0000"+ - "\u18ae\u18af\u0007\u0010\u0000\u0000\u18af\u18b0\u0007\u0013\u0000\u0000"+ - "\u18b0\u18b1\u0005_\u0000\u0000\u18b1\u18b2\u0007\u0010\u0000\u0000\u18b2"+ - "\u18b3\u0007\u0011\u0000\u0000\u18b3\u18b4\u0007\u000f\u0000\u0000\u18b4"+ - "\u18b5\u0007\n\u0000\u0000\u18b5\u18b6\u0007\t\u0000\u0000\u18b6\u18b7"+ - "\u0007\u0010\u0000\u0000\u18b7\u18b8\u0007\u0005\u0000\u0000\u18b8\u18b9"+ - "\u0007\u000f\u0000\u0000\u18b9\u18ba\u0007\u0018\u0000\u0000\u18ba\u0504"+ - "\u0001\u0000\u0000\u0000\u18bb\u18bc\u0007\u0010\u0000\u0000\u18bc\u18bd"+ - "\u0007\u0013\u0000\u0000\u18bd\u18be\u0005_\u0000\u0000\u18be\u18bf\u0007"+ - "\u000e\u0000\u0000\u18bf\u18c0\u0007\u0014\u0000\u0000\u18c0\u18c1\u0007"+ - "\u0005\u0000\u0000\u18c1\u18c2\u0007\r\u0000\u0000\u18c2\u0506\u0001\u0000"+ - "\u0000\u0000\u18c3\u18c4\u0007\u0010\u0000\u0000\u18c4\u18c5\u0007\u0013"+ - "\u0000\u0000\u18c5\u18c6\u0005_\u0000\u0000\u18c6\u18c7\u0007\f\u0000"+ - "\u0000\u18c7\u18c8\u0007\u0005\u0000\u0000\u18c8\u18c9\u0007\u0010\u0000"+ - "\u0000\u18c9\u18ca\u0007\n\u0000\u0000\u18ca\u0508\u0001\u0000\u0000\u0000"+ - "\u18cb\u18cc\u0007\u0010\u0000\u0000\u18cc\u18cd\u0007\u0013\u0000\u0000"+ - "\u18cd\u18ce\u0005_\u0000\u0000\u18ce\u18cf\u0007\u0007\u0000\u0000\u18cf"+ - "\u18d0\u0007\u0016\u0000\u0000\u18d0\u18d1\u0007\u000f\u0000\u0000\u18d1"+ - "\u18d2\u0007\u0012\u0000\u0000\u18d2\u18d3\u0007\n\u0000\u0000\u18d3\u18d4"+ - "\u0007\r\u0000\u0000\u18d4\u050a\u0001\u0000\u0000\u0000\u18d5\u18d9\u0003"+ - "\u050d\u0284\u0000\u18d6\u18d8\u0003\u050f\u0285\u0000\u18d7\u18d6\u0001"+ - "\u0000\u0000\u0000\u18d8\u18db\u0001\u0000\u0000\u0000\u18d9\u18d7\u0001"+ - "\u0000\u0000\u0000\u18d9\u18da\u0001\u0000\u0000\u0000\u18da\u050c\u0001"+ - "\u0000\u0000\u0000\u18db\u18d9\u0001\u0000\u0000\u0000\u18dc\u18e3\u0007"+ - "\u001f\u0000\u0000\u18dd\u18de\u0007 \u0000\u0000\u18de\u18e3\u0004\u0284"+ - "\u0006\u0000\u18df\u18e0\u0007!\u0000\u0000\u18e0\u18e1\u0007\"\u0000"+ - "\u0000\u18e1\u18e3\u0004\u0284\u0007\u0000\u18e2\u18dc\u0001\u0000\u0000"+ - "\u0000\u18e2\u18dd\u0001\u0000\u0000\u0000\u18e2\u18df\u0001\u0000\u0000"+ - "\u0000\u18e3\u050e\u0001\u0000\u0000\u0000\u18e4\u18e7\u0003\u0511\u0286"+ - "\u0000\u18e5\u18e7\u0005$\u0000\u0000\u18e6\u18e4\u0001\u0000\u0000\u0000"+ - "\u18e6\u18e5\u0001\u0000\u0000\u0000\u18e7\u0510\u0001\u0000\u0000\u0000"+ - "\u18e8\u18eb\u0003\u050d\u0284\u0000\u18e9\u18eb\u0007\u0000\u0000\u0000"+ - "\u18ea\u18e8\u0001\u0000\u0000\u0000\u18ea\u18e9\u0001\u0000\u0000\u0000"+ - "\u18eb\u0512\u0001\u0000\u0000\u0000\u18ec\u18ed\u0003\u0515\u0288\u0000"+ - "\u18ed\u18ee\u0005\"\u0000\u0000\u18ee\u0514\u0001\u0000\u0000\u0000\u18ef"+ - "\u18f5\u0005\"\u0000\u0000\u18f0\u18f1\u0005\"\u0000\u0000\u18f1\u18f4"+ - "\u0005\"\u0000\u0000\u18f2\u18f4\b#\u0000\u0000\u18f3\u18f0\u0001\u0000"+ - "\u0000\u0000\u18f3\u18f2\u0001\u0000\u0000\u0000\u18f4\u18f7\u0001\u0000"+ - "\u0000\u0000\u18f5\u18f3\u0001\u0000\u0000\u0000\u18f5\u18f6\u0001\u0000"+ - "\u0000\u0000\u18f6\u0516\u0001\u0000\u0000\u0000\u18f7\u18f5\u0001\u0000"+ - "\u0000\u0000\u18f8\u18f9\u0003\u0519\u028a\u0000\u18f9\u18fa\u0005\"\u0000"+ - "\u0000\u18fa\u0518\u0001\u0000\u0000\u0000\u18fb\u1901\u0005\"\u0000\u0000"+ - "\u18fc\u18fd\u0005\"\u0000\u0000\u18fd\u1900\u0005\"\u0000\u0000\u18fe"+ - "\u1900\b$\u0000\u0000\u18ff\u18fc\u0001\u0000\u0000\u0000\u18ff\u18fe"+ - "\u0001\u0000\u0000\u0000\u1900\u1903\u0001\u0000\u0000\u0000\u1901\u18ff"+ - "\u0001\u0000\u0000\u0000\u1901\u1902\u0001\u0000\u0000\u0000\u1902\u051a"+ - "\u0001\u0000\u0000\u0000\u1903\u1901\u0001\u0000\u0000\u0000\u1904\u1905"+ - "\u0007\u0016\u0000\u0000\u1905\u1906\u0005&\u0000\u0000\u1906\u1907\u0003"+ - "\u0513\u0287\u0000\u1907\u051c\u0001\u0000\u0000\u0000\u1908\u1909\u0007"+ - "\u0016\u0000\u0000\u1909\u190a\u0005&\u0000\u0000\u190a\u190b\u0003\u0515"+ - "\u0288\u0000\u190b\u051e\u0001\u0000\u0000\u0000\u190c\u190d\u0007\u0016"+ - "\u0000\u0000\u190d\u190e\u0005&\u0000\u0000\u190e\u190f\u0003\u0517\u0289"+ - "\u0000\u190f\u0520\u0001\u0000\u0000\u0000\u1910\u1911\u0007\u0016\u0000"+ - "\u0000\u1911\u1912\u0005&\u0000\u0000\u1912\u1913\u0003\u0519\u028a\u0000"+ - "\u1913\u0522\u0001\u0000\u0000\u0000\u1914\u1915\u0003\u0525\u0290\u0000"+ - "\u1915\u1916\u0005\'\u0000\u0000\u1916\u0524\u0001\u0000\u0000\u0000\u1917"+ - "\u1922\u0005\'\u0000\u0000\u1918\u1919\u0005\'\u0000\u0000\u1919\u1921"+ - "\u0005\'\u0000\u0000\u191a\u1921\b%\u0000\u0000\u191b\u191c\u0005\\\u0000"+ - "\u0000\u191c\u191d\u0005\\\u0000\u0000\u191d\u1921\u0005\'\u0000\u0000"+ - "\u191e\u191f\u0005\\\u0000\u0000\u191f\u1921\u0005\'\u0000\u0000\u1920"+ - "\u1918\u0001\u0000\u0000\u0000\u1920\u191a\u0001\u0000\u0000\u0000\u1920"+ - "\u191b\u0001\u0000\u0000\u0000\u1920\u191e\u0001\u0000\u0000\u0000\u1921"+ - "\u1924\u0001\u0000\u0000\u0000\u1922\u1920\u0001\u0000\u0000\u0000\u1922"+ - "\u1923\u0001\u0000\u0000\u0000\u1923\u0526\u0001\u0000\u0000\u0000\u1924"+ - "\u1922\u0001\u0000\u0000\u0000\u1925\u1926\u0007\n\u0000\u0000\u1926\u1927"+ - "\u0005\'\u0000\u0000\u1927\u1928\u0001\u0000\u0000\u0000\u1928\u1929\u0006"+ - "\u0291\u0002\u0000\u1929\u192a\u0006\u0291\u0003\u0000\u192a\u0528\u0001"+ - "\u0000\u0000\u0000\u192b\u192c\u0003\u052b\u0293\u0000\u192c\u192d\u0005"+ - "\'\u0000\u0000\u192d\u052a\u0001\u0000\u0000\u0000\u192e\u192f\u0007\u0016"+ - "\u0000\u0000\u192f\u1930\u0005&\u0000\u0000\u1930\u1931\u0003\u0525\u0290"+ - "\u0000\u1931\u052c\u0001\u0000\u0000\u0000\u1932\u1934\u0005$\u0000\u0000"+ - "\u1933\u1935\u0003\u052f\u0295\u0000\u1934\u1933\u0001\u0000\u0000\u0000"+ - "\u1934\u1935\u0001\u0000\u0000\u0000\u1935\u1936\u0001\u0000\u0000\u0000"+ - "\u1936\u1937\u0005$\u0000\u0000\u1937\u1938\u0006\u0294\u0004\u0000\u1938"+ - "\u1939\u0001\u0000\u0000\u0000\u1939\u193a\u0006\u0294\u0005\u0000\u193a"+ - "\u052e\u0001\u0000\u0000\u0000\u193b\u193f\u0003\u050d\u0284\u0000\u193c"+ - "\u193e\u0003\u0511\u0286\u0000\u193d\u193c\u0001\u0000\u0000\u0000\u193e"+ - "\u1941\u0001\u0000\u0000\u0000\u193f\u193d\u0001\u0000\u0000\u0000\u193f"+ - "\u1940\u0001\u0000\u0000\u0000\u1940\u0530\u0001\u0000\u0000\u0000\u1941"+ - "\u193f\u0001\u0000\u0000\u0000\u1942\u1943\u0003\u0533\u0297\u0000\u1943"+ - "\u1944\u0005\'\u0000\u0000\u1944\u0532\u0001\u0000\u0000\u0000\u1945\u1946"+ - "\u0007\u0012\u0000\u0000\u1946\u194a\u0005\'\u0000\u0000\u1947\u1949\u0007"+ - "&\u0000\u0000\u1948\u1947\u0001\u0000\u0000\u0000\u1949\u194c\u0001\u0000"+ - "\u0000\u0000\u194a\u1948\u0001\u0000\u0000\u0000\u194a\u194b\u0001\u0000"+ - "\u0000\u0000\u194b\u0534\u0001\u0000\u0000\u0000\u194c\u194a\u0001\u0000"+ - "\u0000\u0000\u194d\u194e\u0003\u0537\u0299\u0000\u194e\u194f\u0005\'\u0000"+ - "\u0000\u194f\u0536\u0001\u0000\u0000\u0000\u1950\u1951\u0007\u0012\u0000"+ - "\u0000\u1951\u1952\u0003\u0525\u0290\u0000\u1952\u0538\u0001\u0000\u0000"+ - "\u0000\u1953\u1954\u0003\u053b\u029b\u0000\u1954\u1955\u0005\'\u0000\u0000"+ - "\u1955\u053a\u0001\u0000\u0000\u0000\u1956\u1957\u0007\u001a\u0000\u0000"+ - "\u1957\u195b\u0005\'\u0000\u0000\u1958\u195a\u0007\'\u0000\u0000\u1959"+ - "\u1958\u0001\u0000\u0000\u0000\u195a\u195d\u0001\u0000\u0000\u0000\u195b"+ - "\u1959\u0001\u0000\u0000\u0000\u195b\u195c\u0001\u0000\u0000\u0000\u195c"+ - "\u053c\u0001\u0000\u0000\u0000\u195d\u195b\u0001\u0000\u0000\u0000\u195e"+ - "\u195f\u0003\u053f\u029d\u0000\u195f\u1960\u0005\'\u0000\u0000\u1960\u053e"+ - "\u0001\u0000\u0000\u0000\u1961\u1962\u0007\u001a\u0000\u0000\u1962\u1963"+ - "\u0003\u0525\u0290\u0000\u1963\u0540\u0001\u0000\u0000\u0000\u1964\u1965"+ - "\u0003\u0547\u02a1\u0000\u1965\u0542\u0001\u0000\u0000\u0000\u1966\u1967"+ - "\u0003\u0547\u02a1\u0000\u1967\u1968\u0005.\u0000\u0000\u1968\u1969\u0005"+ - ".\u0000\u0000\u1969\u196a\u0001\u0000\u0000\u0000\u196a\u196b\u0006\u029f"+ - "\u0006\u0000\u196b\u0544\u0001\u0000\u0000\u0000\u196c\u196d\u0003\u0547"+ - "\u02a1\u0000\u196d\u196f\u0005.\u0000\u0000\u196e\u1970\u0003\u0547\u02a1"+ - "\u0000\u196f\u196e\u0001\u0000\u0000\u0000\u196f\u1970\u0001\u0000\u0000"+ - "\u0000\u1970\u1976\u0001\u0000\u0000\u0000\u1971\u1973\u0007\n\u0000\u0000"+ - "\u1972\u1974\u0007\u0001\u0000\u0000\u1973\u1972\u0001\u0000\u0000\u0000"+ - "\u1973\u1974\u0001\u0000\u0000\u0000\u1974\u1975\u0001\u0000\u0000\u0000"+ - "\u1975\u1977\u0003\u0547\u02a1\u0000\u1976\u1971\u0001\u0000\u0000\u0000"+ - "\u1976\u1977\u0001\u0000\u0000\u0000\u1977\u1989\u0001\u0000\u0000\u0000"+ - "\u1978\u1979\u0005.\u0000\u0000\u1979\u197f\u0003\u0547\u02a1\u0000\u197a"+ - "\u197c\u0007\n\u0000\u0000\u197b\u197d\u0007\u0001\u0000\u0000\u197c\u197b"+ - "\u0001\u0000\u0000\u0000\u197c\u197d\u0001\u0000\u0000\u0000\u197d\u197e"+ - "\u0001\u0000\u0000\u0000\u197e\u1980\u0003\u0547\u02a1\u0000\u197f\u197a"+ - "\u0001\u0000\u0000\u0000\u197f\u1980\u0001\u0000\u0000\u0000\u1980\u1989"+ - "\u0001\u0000\u0000\u0000\u1981\u1982\u0003\u0547\u02a1\u0000\u1982\u1984"+ - "\u0007\n\u0000\u0000\u1983\u1985\u0007\u0001\u0000\u0000\u1984\u1983\u0001"+ - "\u0000\u0000\u0000\u1984\u1985\u0001\u0000\u0000\u0000\u1985\u1986\u0001"+ - "\u0000\u0000\u0000\u1986\u1987\u0003\u0547\u02a1\u0000\u1987\u1989\u0001"+ - "\u0000\u0000\u0000\u1988\u196c\u0001\u0000\u0000\u0000\u1988\u1978\u0001"+ - "\u0000\u0000\u0000\u1988\u1981\u0001\u0000\u0000\u0000\u1989\u0546\u0001"+ - "\u0000\u0000\u0000\u198a\u198c\u0007\u0000\u0000\u0000\u198b\u198a\u0001"+ - "\u0000\u0000\u0000\u198c\u198d\u0001\u0000\u0000\u0000\u198d\u198b\u0001"+ - "\u0000\u0000\u0000\u198d\u198e\u0001\u0000\u0000\u0000\u198e\u0548\u0001"+ - "\u0000\u0000\u0000\u198f\u1990\u0005:\u0000\u0000\u1990\u1991\u0005\""+ - "\u0000\u0000\u1991\u1999\u0001\u0000\u0000\u0000\u1992\u1993\u0005\\\u0000"+ - "\u0000\u1993\u1998\t\u0000\u0000\u0000\u1994\u1995\u0005\"\u0000\u0000"+ - "\u1995\u1998\u0005\"\u0000\u0000\u1996\u1998\b(\u0000\u0000\u1997\u1992"+ - "\u0001\u0000\u0000\u0000\u1997\u1994\u0001\u0000\u0000\u0000\u1997\u1996"+ - "\u0001\u0000\u0000\u0000\u1998\u199b\u0001\u0000\u0000\u0000\u1999\u1997"+ - "\u0001\u0000\u0000\u0000\u1999\u199a\u0001\u0000\u0000\u0000\u199a\u199c"+ - "\u0001\u0000\u0000\u0000\u199b\u1999\u0001\u0000\u0000\u0000\u199c\u199d"+ - "\u0005\"\u0000\u0000\u199d\u054a\u0001\u0000\u0000\u0000\u199e\u19a0\u0007"+ - ")\u0000\u0000\u199f\u199e\u0001\u0000\u0000\u0000\u19a0\u19a1\u0001\u0000"+ - "\u0000\u0000\u19a1\u199f\u0001\u0000\u0000\u0000\u19a1\u19a2\u0001\u0000"+ - "\u0000\u0000\u19a2\u19a3\u0001\u0000\u0000\u0000\u19a3\u19a4\u0006\u02a3"+ - "\u0007\u0000\u19a4\u054c\u0001\u0000\u0000\u0000\u19a5\u19a7\u0005\r\u0000"+ - "\u0000\u19a6\u19a8\u0005\n\u0000\u0000\u19a7\u19a6\u0001\u0000\u0000\u0000"+ - "\u19a7\u19a8\u0001\u0000\u0000\u0000\u19a8\u19ab\u0001\u0000\u0000\u0000"+ - "\u19a9\u19ab\u0005\n\u0000\u0000\u19aa\u19a5\u0001\u0000\u0000\u0000\u19aa"+ - "\u19a9\u0001\u0000\u0000\u0000\u19ab\u19ac\u0001\u0000\u0000\u0000\u19ac"+ - "\u19ad\u0006\u02a4\u0007\u0000\u19ad\u054e\u0001\u0000\u0000\u0000\u19ae"+ - "\u19af\u0005-\u0000\u0000\u19af\u19b0\u0005-\u0000\u0000\u19b0\u19b4\u0001"+ - "\u0000\u0000\u0000\u19b1\u19b3\b*\u0000\u0000\u19b2\u19b1\u0001\u0000"+ - "\u0000\u0000\u19b3\u19b6\u0001\u0000\u0000\u0000\u19b4\u19b2\u0001\u0000"+ - "\u0000\u0000\u19b4\u19b5\u0001\u0000\u0000\u0000\u19b5\u19b7\u0001\u0000"+ - "\u0000\u0000\u19b6\u19b4\u0001\u0000\u0000\u0000\u19b7\u19b8\u0006\u02a5"+ - "\u0007\u0000\u19b8\u0550\u0001\u0000\u0000\u0000\u19b9\u19ba\u0005/\u0000"+ - "\u0000\u19ba\u19bb\u0005*\u0000\u0000\u19bb\u19d2\u0001\u0000\u0000\u0000"+ - "\u19bc\u19be\u0005/\u0000\u0000\u19bd\u19bc\u0001\u0000\u0000\u0000\u19be"+ - "\u19c1\u0001\u0000\u0000\u0000\u19bf\u19bd\u0001\u0000\u0000\u0000\u19bf"+ - "\u19c0\u0001\u0000\u0000\u0000\u19c0\u19c2\u0001\u0000\u0000\u0000\u19c1"+ - "\u19bf\u0001\u0000\u0000\u0000\u19c2\u19d1\u0003\u0551\u02a6\u0000\u19c3"+ - "\u19d1\b+\u0000\u0000\u19c4\u19c6\u0005/\u0000\u0000\u19c5\u19c4\u0001"+ - "\u0000\u0000\u0000\u19c6\u19c7\u0001\u0000\u0000\u0000\u19c7\u19c5\u0001"+ - "\u0000\u0000\u0000\u19c7\u19c8\u0001\u0000\u0000\u0000\u19c8\u19c9\u0001"+ - "\u0000\u0000\u0000\u19c9\u19d1\b+\u0000\u0000\u19ca\u19cc\u0005*\u0000"+ - "\u0000\u19cb\u19ca\u0001\u0000\u0000\u0000\u19cc\u19cd\u0001\u0000\u0000"+ - "\u0000\u19cd\u19cb\u0001\u0000\u0000\u0000\u19cd\u19ce\u0001\u0000\u0000"+ - "\u0000\u19ce\u19cf\u0001\u0000\u0000\u0000\u19cf\u19d1\b+\u0000\u0000"+ - "\u19d0\u19bf\u0001\u0000\u0000\u0000\u19d0\u19c3\u0001\u0000\u0000\u0000"+ - "\u19d0\u19c5\u0001\u0000\u0000\u0000\u19d0\u19cb\u0001\u0000\u0000\u0000"+ - "\u19d1\u19d4\u0001\u0000\u0000\u0000\u19d2\u19d0\u0001\u0000\u0000\u0000"+ - "\u19d2\u19d3\u0001\u0000\u0000\u0000\u19d3\u19d8\u0001\u0000\u0000\u0000"+ - "\u19d4\u19d2\u0001\u0000\u0000\u0000\u19d5\u19d7\u0005*\u0000\u0000\u19d6"+ - "\u19d5\u0001\u0000\u0000\u0000\u19d7\u19da\u0001\u0000\u0000\u0000\u19d8"+ - "\u19d6\u0001\u0000\u0000\u0000\u19d8\u19d9\u0001\u0000\u0000\u0000\u19d9"+ - "\u19db\u0001\u0000\u0000\u0000\u19da\u19d8\u0001\u0000\u0000\u0000\u19db"+ - "\u19dc\u0005*\u0000\u0000\u19dc\u19dd\u0005/\u0000\u0000\u19dd\u19de\u0001"+ - "\u0000\u0000\u0000\u19de\u19df\u0006\u02a6\u0007\u0000\u19df\u0552\u0001"+ - "\u0000\u0000\u0000\u19e0\u19e1\u0005/\u0000\u0000\u19e1\u19e2\u0005*\u0000"+ - "\u0000\u19e2\u19fb\u0001\u0000\u0000\u0000\u19e3\u19e5\u0005/\u0000\u0000"+ - "\u19e4\u19e3\u0001\u0000\u0000\u0000\u19e5\u19e8\u0001\u0000\u0000\u0000"+ - "\u19e6\u19e4\u0001\u0000\u0000\u0000\u19e6\u19e7\u0001\u0000\u0000\u0000"+ - "\u19e7\u19e9\u0001\u0000\u0000\u0000\u19e8\u19e6\u0001\u0000\u0000\u0000"+ - "\u19e9\u19fa\u0003\u0551\u02a6\u0000\u19ea\u19fa\b+\u0000\u0000\u19eb"+ - "\u19ed\u0005/\u0000\u0000\u19ec\u19eb\u0001\u0000\u0000\u0000\u19ed\u19ee"+ - "\u0001\u0000\u0000\u0000\u19ee\u19ec\u0001\u0000\u0000\u0000\u19ee\u19ef"+ - "\u0001\u0000\u0000\u0000\u19ef\u19f0\u0001\u0000\u0000\u0000\u19f0\u19f8"+ - "\b+\u0000\u0000\u19f1\u19f3\u0005*\u0000\u0000\u19f2\u19f1\u0001\u0000"+ - "\u0000\u0000\u19f3\u19f4\u0001\u0000\u0000\u0000\u19f4\u19f2\u0001\u0000"+ - "\u0000\u0000\u19f4\u19f5\u0001\u0000\u0000\u0000\u19f5\u19f6\u0001\u0000"+ - "\u0000\u0000\u19f6\u19f8\b+\u0000\u0000\u19f7\u19ec\u0001\u0000\u0000"+ - "\u0000\u19f7\u19f2\u0001\u0000\u0000\u0000\u19f8\u19fa\u0001\u0000\u0000"+ - "\u0000\u19f9\u19e6\u0001\u0000\u0000\u0000\u19f9\u19ea\u0001\u0000\u0000"+ - "\u0000\u19f9\u19f7\u0001\u0000\u0000\u0000\u19fa\u19fd\u0001\u0000\u0000"+ - "\u0000\u19fb\u19f9\u0001\u0000\u0000\u0000\u19fb\u19fc\u0001\u0000\u0000"+ - "\u0000\u19fc\u1a0f\u0001\u0000\u0000\u0000\u19fd\u19fb\u0001\u0000\u0000"+ - "\u0000\u19fe\u1a00\u0005/\u0000\u0000\u19ff\u19fe\u0001\u0000\u0000\u0000"+ - "\u1a00\u1a01\u0001\u0000\u0000\u0000\u1a01\u19ff\u0001\u0000\u0000\u0000"+ - "\u1a01\u1a02\u0001\u0000\u0000\u0000\u1a02\u1a10\u0001\u0000\u0000\u0000"+ - "\u1a03\u1a05\u0005*\u0000\u0000\u1a04\u1a03\u0001\u0000\u0000\u0000\u1a05"+ - "\u1a06\u0001\u0000\u0000\u0000\u1a06\u1a04\u0001\u0000\u0000\u0000\u1a06"+ - "\u1a07\u0001\u0000\u0000\u0000\u1a07\u1a10\u0001\u0000\u0000\u0000\u1a08"+ - "\u1a0a\u0005/\u0000\u0000\u1a09\u1a08\u0001\u0000\u0000\u0000\u1a0a\u1a0d"+ - "\u0001\u0000\u0000\u0000\u1a0b\u1a09\u0001\u0000\u0000\u0000\u1a0b\u1a0c"+ - "\u0001\u0000\u0000\u0000\u1a0c\u1a0e\u0001\u0000\u0000\u0000\u1a0d\u1a0b"+ - "\u0001\u0000\u0000\u0000\u1a0e\u1a10\u0003\u0553\u02a7\u0000\u1a0f\u19ff"+ - "\u0001\u0000\u0000\u0000\u1a0f\u1a04\u0001\u0000\u0000\u0000\u1a0f\u1a0b"+ - "\u0001\u0000\u0000\u0000\u1a0f\u1a10\u0001\u0000\u0000\u0000\u1a10\u1a11"+ - "\u0001\u0000\u0000\u0000\u1a11\u1a12\u0006\u02a7\b\u0000\u1a12\u0554\u0001"+ - "\u0000\u0000\u0000\u1a13\u1a1f\u0005\\\u0000\u0000\u1a14\u1a1e\b,\u0000"+ - "\u0000\u1a15\u1a19\u0005\"\u0000\u0000\u1a16\u1a18\b-\u0000\u0000\u1a17"+ - "\u1a16\u0001\u0000\u0000\u0000\u1a18\u1a1b\u0001\u0000\u0000\u0000\u1a19"+ - "\u1a17\u0001\u0000\u0000\u0000\u1a19\u1a1a\u0001\u0000\u0000\u0000\u1a1a"+ - "\u1a1c\u0001\u0000\u0000\u0000\u1a1b\u1a19\u0001\u0000\u0000\u0000\u1a1c"+ - "\u1a1e\u0005\"\u0000\u0000\u1a1d\u1a14\u0001\u0000\u0000\u0000\u1a1d\u1a15"+ - "\u0001\u0000\u0000\u0000\u1a1e\u1a21\u0001\u0000\u0000\u0000\u1a1f\u1a1d"+ - "\u0001\u0000\u0000\u0000\u1a1f\u1a20\u0001\u0000\u0000\u0000\u1a20\u1a29"+ - "\u0001\u0000\u0000\u0000\u1a21\u1a1f\u0001\u0000\u0000\u0000\u1a22\u1a26"+ - "\u0005\"\u0000\u0000\u1a23\u1a25\b-\u0000\u0000\u1a24\u1a23\u0001\u0000"+ - "\u0000\u0000\u1a25\u1a28\u0001\u0000\u0000\u0000\u1a26\u1a24\u0001\u0000"+ - "\u0000\u0000\u1a26\u1a27\u0001\u0000\u0000\u0000\u1a27\u1a2a\u0001\u0000"+ - "\u0000\u0000\u1a28\u1a26\u0001\u0000\u0000\u0000\u1a29\u1a22\u0001\u0000"+ - "\u0000\u0000\u1a29\u1a2a\u0001\u0000\u0000\u0000\u1a2a\u0556\u0001\u0000"+ - "\u0000\u0000\u1a2b\u1a2c\u0005\\\u0000\u0000\u1a2c\u1a2d\u0005\\\u0000"+ - "\u0000\u1a2d\u0558\u0001\u0000\u0000\u0000\u1a2e\u1a2f\t\u0000\u0000\u0000"+ - "\u1a2f\u055a\u0001\u0000\u0000\u0000\u1a30\u1a31\u0003\u055f\u02ad\u0000"+ - "\u1a31\u1a32\u0005\'\u0000\u0000\u1a32\u1a33\u0001\u0000\u0000\u0000\u1a33"+ - "\u1a34\u0006\u02ab\t\u0000\u1a34\u055c\u0001\u0000\u0000\u0000\u1a35\u1a37"+ - "\u0003\u055f\u02ad\u0000\u1a36\u1a38\u0005\\\u0000\u0000\u1a37\u1a36\u0001"+ - "\u0000\u0000\u0000\u1a37\u1a38\u0001\u0000\u0000\u0000\u1a38\u1a39\u0001"+ - "\u0000\u0000\u0000\u1a39\u1a3a\u0005\u0000\u0000\u0001\u1a3a\u055e\u0001"+ - "\u0000\u0000\u0000\u1a3b\u1a3c\u0005\\\u0000\u0000\u1a3c\u1a56\u0005\'"+ - "\u0000\u0000\u1a3d\u1a3e\u0005\'\u0000\u0000\u1a3e\u1a3f\u0005\'\u0000"+ - "\u0000\u1a3f\u1a56\u0005\'\u0000\u0000\u1a40\u1a52\u0005\\\u0000\u0000"+ - "\u1a41\u1a42\u0005x\u0000\u0000\u1a42\u1a53\u0007\'\u0000\u0000\u1a43"+ - "\u1a44\u0005u\u0000\u0000\u1a44\u1a45\u0007\'\u0000\u0000\u1a45\u1a46"+ - "\u0007\'\u0000\u0000\u1a46\u1a47\u0007\'\u0000\u0000\u1a47\u1a53\u0007"+ - "\'\u0000\u0000\u1a48\u1a49\u0005U\u0000\u0000\u1a49\u1a4a\u0007\'\u0000"+ - "\u0000\u1a4a\u1a4b\u0007\'\u0000\u0000\u1a4b\u1a4c\u0007\'\u0000\u0000"+ - "\u1a4c\u1a4d\u0007\'\u0000\u0000\u1a4d\u1a4e\u0007\'\u0000\u0000\u1a4e"+ - "\u1a4f\u0007\'\u0000\u0000\u1a4f\u1a50\u0007\'\u0000\u0000\u1a50\u1a53"+ - "\u0007\'\u0000\u0000\u1a51\u1a53\b.\u0000\u0000\u1a52\u1a41\u0001\u0000"+ - "\u0000\u0000\u1a52\u1a43\u0001\u0000\u0000\u0000\u1a52\u1a48\u0001\u0000"+ - "\u0000\u0000\u1a52\u1a51\u0001\u0000\u0000\u0000\u1a53\u1a56\u0001\u0000"+ - "\u0000\u0000\u1a54\u1a56\b/\u0000\u0000\u1a55\u1a3b\u0001\u0000\u0000"+ - "\u0000\u1a55\u1a3d\u0001\u0000\u0000\u0000\u1a55\u1a40\u0001\u0000\u0000"+ - "\u0000\u1a55\u1a54\u0001\u0000\u0000\u0000\u1a56\u1a59\u0001\u0000\u0000"+ - "\u0000\u1a57\u1a55\u0001\u0000\u0000\u0000\u1a57\u1a58\u0001\u0000\u0000"+ - "\u0000\u1a58\u0560\u0001\u0000\u0000\u0000\u1a59\u1a57\u0001\u0000\u0000"+ - "\u0000\u1a5a\u1a5b\u0003\u0565\u02b0\u0000\u1a5b\u1a5c\u0005\'\u0000\u0000"+ - "\u1a5c\u1a5d\u0001\u0000\u0000\u0000\u1a5d\u1a5e\u0006\u02ae\t\u0000\u1a5e"+ - "\u0562\u0001\u0000\u0000\u0000\u1a5f\u1a61\u0003\u0565\u02b0\u0000\u1a60"+ - "\u1a62\u0005\\\u0000\u0000\u1a61\u1a60\u0001\u0000\u0000\u0000\u1a61\u1a62"+ - "\u0001\u0000\u0000\u0000\u1a62\u1a63\u0001\u0000\u0000\u0000\u1a63\u1a64"+ - "\u0005\u0000\u0000\u0001\u1a64\u0564\u0001\u0000\u0000\u0000\u1a65\u1a66"+ - "\u0005\'\u0000\u0000\u1a66\u1a6b\u0005\'\u0000\u0000\u1a67\u1a68\u0005"+ - "\\\u0000\u0000\u1a68\u1a6b\t\u0000\u0000\u0000\u1a69\u1a6b\b/\u0000\u0000"+ - "\u1a6a\u1a65\u0001\u0000\u0000\u0000\u1a6a\u1a67\u0001\u0000\u0000\u0000"+ - "\u1a6a\u1a69\u0001\u0000\u0000\u0000\u1a6b\u1a6e\u0001\u0000\u0000\u0000"+ - "\u1a6c\u1a6a\u0001\u0000\u0000\u0000\u1a6c\u1a6d\u0001\u0000\u0000\u0000"+ - "\u1a6d\u0566\u0001\u0000\u0000\u0000\u1a6e\u1a6c\u0001\u0000\u0000\u0000"+ - "\u1a6f\u1a70\u0003\u054b\u02a3\u0000\u1a70\u1a71\u0001\u0000\u0000\u0000"+ - "\u1a71\u1a72\u0006\u02b1\n\u0000\u1a72\u1a73\u0006\u02b1\u0007\u0000\u1a73"+ - "\u0568\u0001\u0000\u0000\u0000\u1a74\u1a75\u0003\u054d\u02a4\u0000\u1a75"+ - "\u1a76\u0001\u0000\u0000\u0000\u1a76\u1a77\u0006\u02b2\u000b\u0000\u1a77"+ - "\u1a78\u0006\u02b2\u0007\u0000\u1a78\u1a79\u0006\u02b2\f\u0000\u1a79\u056a"+ - "\u0001\u0000\u0000\u0000\u1a7a\u1a7b\u0003\u054b\u02a3\u0000\u1a7b\u1a7c"+ - "\u0001\u0000\u0000\u0000\u1a7c\u1a7d\u0006\u02b3\n\u0000\u1a7d\u1a7e\u0006"+ - "\u02b3\u0007\u0000\u1a7e\u056c\u0001\u0000\u0000\u0000\u1a7f\u1a80\u0003"+ - "\u054d\u02a4\u0000\u1a80\u1a81\u0001\u0000\u0000\u0000\u1a81\u1a82\u0006"+ - "\u02b4\u000b\u0000\u1a82\u1a83\u0006\u02b4\u0007\u0000\u1a83\u056e\u0001"+ - "\u0000\u0000\u0000\u1a84\u1a85\u0005\'\u0000\u0000\u1a85\u1a86\u0001\u0000"+ - "\u0000\u0000\u1a86\u1a87\u0006\u02b5\u0002\u0000\u1a87\u1a88\u0006\u02b5"+ - "\r\u0000\u1a88\u0570\u0001\u0000\u0000\u0000\u1a89\u1a8b\b0\u0000\u0000"+ - "\u1a8a\u1a89\u0001\u0000\u0000\u0000\u1a8b\u1a8c\u0001\u0000\u0000\u0000"+ - "\u1a8c\u1a8a\u0001\u0000\u0000\u0000\u1a8c\u1a8d\u0001\u0000\u0000\u0000"+ - "\u1a8d\u1a96\u0001\u0000\u0000\u0000\u1a8e\u1a92\u0005$\u0000\u0000\u1a8f"+ - "\u1a91\b0\u0000\u0000\u1a90\u1a8f\u0001\u0000\u0000\u0000\u1a91\u1a94"+ - "\u0001\u0000\u0000\u0000\u1a92\u1a90\u0001\u0000\u0000\u0000\u1a92\u1a93"+ - "\u0001\u0000\u0000\u0000\u1a93\u1a96\u0001\u0000\u0000\u0000\u1a94\u1a92"+ - "\u0001\u0000\u0000\u0000\u1a95\u1a8a\u0001\u0000\u0000\u0000\u1a95\u1a8e"+ - "\u0001\u0000\u0000\u0000\u1a96\u0572\u0001\u0000\u0000\u0000\u1a97\u1a99"+ - "\u0005$\u0000\u0000\u1a98\u1a9a\u0003\u052f\u0295\u0000\u1a99\u1a98\u0001"+ - "\u0000\u0000\u0000\u1a99\u1a9a\u0001\u0000\u0000\u0000\u1a9a\u1a9b\u0001"+ - "\u0000\u0000\u0000\u1a9b\u1a9c\u0005$\u0000\u0000\u1a9c\u1a9d\u0001\u0000"+ - "\u0000\u0000\u1a9d\u1a9e\u0004\u02b7\b\u0000\u1a9e\u1a9f\u0006\u02b7\u000e"+ - "\u0000\u1a9f\u1aa0\u0001\u0000\u0000\u0000\u1aa0\u1aa1\u0006\u02b7\u000f"+ - "\u0000\u1aa1\u0574\u0001\u0000\u0000\u0000O\u0000\u0001\u0002\u0003\u0004"+ - "\u057e\u05c6\u05cc\u05ce\u05d3\u05d7\u05d9\u05eb\u05ed\u05f6\u05f8\u05fd"+ - "\u0602\u0604\u18d9\u18e2\u18e6\u18ea\u18f3\u18f5\u18ff\u1901\u1920\u1922"+ - "\u1934\u193f\u194a\u195b\u196f\u1973\u1976\u197c\u197f\u1984\u1988\u198d"+ - "\u1997\u1999\u19a1\u19a7\u19aa\u19b4\u19bf\u19c7\u19cd\u19d0\u19d2\u19d8"+ - "\u19e6\u19ee\u19f4\u19f7\u19f9\u19fb\u1a01\u1a06\u1a0b\u1a0f\u1a19\u1a1d"+ - "\u1a1f\u1a26\u1a29\u1a37\u1a52\u1a55\u1a57\u1a61\u1a6a\u1a6c\u1a8c\u1a92"+ - "\u1a95\u1a99\u0010\u0001\u001f\u0000\u0007\u001f\u0000\u0003\u0000\u0000"+ - "\u0005\u0001\u0000\u0001\u0294\u0001\u0005\u0004\u0000\u0001\u029f\u0002"+ - "\u0000\u0001\u0000\u0001\u02a7\u0003\u0002\u0002\u0000\u0007\u0299\u0000"+ - "\u0007\u029a\u0000\u0002\u0003\u0000\u0002\u0001\u0000\u0001\u02b7\u0004"+ - "\u0004\u0000\u0000"; + "\u0000\u125a\u125b\u0007\u0007\u0000\u0000\u125b\u125c\u0007\n\u0000\u0000"+ + "\u125c\u125d\u0007\r\u0000\u0000\u125d\u125e\u0007\u0005\u0000\u0000\u125e"+ + "\u125f\u0007\u0010\u0000\u0000\u125f\u1260\u0007\n\u0000\u0000\u1260\u1261"+ + "\u0007\f\u0000\u0000\u1261\u037e\u0001\u0000\u0000\u0000\u1262\u1263\u0007"+ + "\u0006\u0000\u0000\u1263\u1264\u0007\u0013\u0000\u0000\u1264\u1265\u0007"+ + "\u0017\u0000\u0000\u1265\u1266\u0007\u0017\u0000\u0000\u1266\u1267\u0007"+ + "\n\u0000\u0000\u1267\u1268\u0007\f\u0000\u0000\u1268\u0380\u0001\u0000"+ + "\u0000\u0000\u1269\u126a\u0007\t\u0000\u0000\u126a\u126b\u0007\u0010\u0000"+ + "\u0000\u126b\u126c\u0007\u0013\u0000\u0000\u126c\u126d\u0007\r\u0000\u0000"+ + "\u126d\u126e\u0007\n\u0000\u0000\u126e\u126f\u0007\f\u0000\u0000\u126f"+ + "\u0382\u0001\u0000\u0000\u0000\u1270\u1271\u0007\u0011\u0000\u0000\u1271"+ + "\u1272\u0007\u0007\u0000\u0000\u1272\u1273\u0007\u000e\u0000\u0000\u1273"+ + "\u1274\u0007\u0006\u0000\u0000\u1274\u1275\u0007\u0016\u0000\u0000\u1275"+ + "\u1276\u0007\f\u0000\u0000\u1276\u1277\u0007\n\u0000\u0000\u1277\u0384"+ + "\u0001\u0000\u0000\u0000\u1278\u1279\u0007\r\u0000\u0000\u1279\u127a\u0007"+ + "\u0013\u0000\u0000\u127a\u127b\u0007\u0016\u0000\u0000\u127b\u127c\u0007"+ + "\u0010\u0000\u0000\u127c\u127d\u0007\u0011\u0000\u0000\u127d\u127e\u0007"+ + "\u0007\u0000\u0000\u127e\u127f\u0007\n\u0000\u0000\u127f\u0386\u0001\u0000"+ + "\u0000\u0000\u1280\u1281\u0007\u0010\u0000\u0000\u1281\u1282\u0007\r\u0000"+ + "\u0000\u1282\u1283\u0007\u0005\u0000\u0000\u1283\u1284\u0007\u0007\u0000"+ + "\u0000\u1284\u1285\u0007\t\u0000\u0000\u1285\u1286\u0007\u0019\u0000\u0000"+ + "\u1286\u1287\u0007\u0013\u0000\u0000\u1287\u1288\u0007\r\u0000\u0000\u1288"+ + "\u1289\u0007\u000f\u0000\u0000\u1289\u0388\u0001\u0000\u0000\u0000\u128a"+ + "\u128b\u0007\u0011\u0000\u0000\u128b\u128c\u0007\u000f\u0000\u0000\u128c"+ + "\u128d\u0007\u0018\u0000\u0000\u128d\u128e\u0007\u0013\u0000\u0000\u128e"+ + "\u128f\u0007\r\u0000\u0000\u128f\u1290\u0007\u0010\u0000\u0000\u1290\u038a"+ + "\u0001\u0000\u0000\u0000\u1291\u1292\u0007\u0018\u0000\u0000\u1292\u1293"+ + "\u0007\u0013\u0000\u0000\u1293\u1294\u0007\u0006\u0000\u0000\u1294\u1295"+ + "\u0007\u0011\u0000\u0000\u1295\u1296\u0007\u000e\u0000\u0000\u1296\u1297"+ + "\u0007\b\u0000\u0000\u1297\u038c\u0001\u0000\u0000\u0000\u1298\u1299\u0007"+ + "\u000f\u0000\u0000\u1299\u129a\u0007\n\u0000\u0000\u129a\u129b\u0007\u0010"+ + "\u0000\u0000\u129b\u129c\u0007\u0014\u0000\u0000\u129c\u129d\u0007\u0013"+ + "\u0000\u0000\u129d\u129e\u0007\f\u0000\u0000\u129e\u038e\u0001\u0000\u0000"+ + "\u0000\u129f\u12a0\u0007\r\u0000\u0000\u12a0\u12a1\u0007\n\u0000\u0000"+ + "\u12a1\u12a2\u0007\u0019\u0000\u0000\u12a2\u12a3\u0007\n\u0000\u0000\u12a3"+ + "\u12a4\u0007\r\u0000\u0000\u12a4\u12a5\u0007\n\u0000\u0000\u12a5\u12a6"+ + "\u0007\u0007\u0000\u0000\u12a6\u12a7\u0007\u000e\u0000\u0000\u12a7\u12a8"+ + "\u0007\u0011\u0000\u0000\u12a8\u12a9\u0007\u0007\u0000\u0000\u12a9\u12aa"+ + "\u0007\u0017\u0000\u0000\u12aa\u0390\u0001\u0000\u0000\u0000\u12ab\u12ac"+ + "\u0007\u0007\u0000\u0000\u12ac\u12ad\u0007\n\u0000\u0000\u12ad\u12ae\u0007"+ + "\u001d\u0000\u0000\u12ae\u0392\u0001\u0000\u0000\u0000\u12af\u12b0\u0007"+ + "\u0013\u0000\u0000\u12b0\u12b1\u0007\u0006\u0000\u0000\u12b1\u12b2\u0007"+ + "\f\u0000\u0000\u12b2\u0394\u0001\u0000\u0000\u0000\u12b3\u12b4\u0007\u001b"+ + "\u0000\u0000\u12b4\u12b5\u0007\u0005\u0000\u0000\u12b5\u12b6\u0007\u0006"+ + "\u0000\u0000\u12b6\u12b7\u0007\u0016\u0000\u0000\u12b7\u12b8\u0007\n\u0000"+ + "\u0000\u12b8\u0396\u0001\u0000\u0000\u0000\u12b9\u12ba\u0007\t\u0000\u0000"+ + "\u12ba\u12bb\u0007\u0016\u0000\u0000\u12bb\u12bc\u0007\u0012\u0000\u0000"+ + "\u12bc\u12bd\u0007\t\u0000\u0000\u12bd\u12be\u0007\u000e\u0000\u0000\u12be"+ + "\u12bf\u0007\r\u0000\u0000\u12bf\u12c0\u0007\u0011\u0000\u0000\u12c0\u12c1"+ + "\u0007\u0018\u0000\u0000\u12c1\u12c2\u0007\u0010\u0000\u0000\u12c2\u12c3"+ + "\u0007\u0011\u0000\u0000\u12c3\u12c4\u0007\u0013\u0000\u0000\u12c4\u12c5"+ + "\u0007\u0007\u0000\u0000\u12c5\u0398\u0001\u0000\u0000\u0000\u12c6\u12c7"+ + "\u0007\u0018\u0000\u0000\u12c7\u12c8\u0007\u0016\u0000\u0000\u12c8\u12c9"+ + "\u0007\u0012\u0000\u0000\u12c9\u12ca\u0007\u0006\u0000\u0000\u12ca\u12cb"+ + "\u0007\u0011\u0000\u0000\u12cb\u12cc\u0007\u000e\u0000\u0000\u12cc\u12cd"+ + "\u0007\u0005\u0000\u0000\u12cd\u12ce\u0007\u0010\u0000\u0000\u12ce\u12cf"+ + "\u0007\u0011\u0000\u0000\u12cf\u12d0\u0007\u0013\u0000\u0000\u12d0\u12d1"+ + "\u0007\u0007\u0000\u0000\u12d1\u039a\u0001\u0000\u0000\u0000\u12d2\u12d3"+ + "\u0007\u0013\u0000\u0000\u12d3\u12d4\u0007\u0016\u0000\u0000\u12d4\u12d5"+ + "\u0007\u0010\u0000\u0000\u12d5\u039c\u0001\u0000\u0000\u0000\u12d6\u12d7"+ + "\u0007\n\u0000\u0000\u12d7\u12d8\u0007\u0007\u0000\u0000\u12d8\u12d9\u0007"+ + "\f\u0000\u0000\u12d9\u039e\u0001\u0000\u0000\u0000\u12da\u12db\u0007\r"+ + "\u0000\u0000\u12db\u12dc\u0007\u0013\u0000\u0000\u12dc\u12dd\u0007\u0016"+ + "\u0000\u0000\u12dd\u12de\u0007\u0010\u0000\u0000\u12de\u12df\u0007\u0011"+ + "\u0000\u0000\u12df\u12e0\u0007\u0007\u0000\u0000\u12e0\u12e1\u0007\n\u0000"+ + "\u0000\u12e1\u12e2\u0007\t\u0000\u0000\u12e2\u03a0\u0001\u0000\u0000\u0000"+ + "\u12e3\u12e4\u0007\t\u0000\u0000\u12e4\u12e5\u0007\u000e\u0000\u0000\u12e5"+ + "\u12e6\u0007\u0014\u0000\u0000\u12e6\u12e7\u0007\n\u0000\u0000\u12e7\u12e8"+ + "\u0007\u000f\u0000\u0000\u12e8\u12e9\u0007\u0005\u0000\u0000\u12e9\u12ea"+ + "\u0007\t\u0000\u0000\u12ea\u03a2\u0001\u0000\u0000\u0000\u12eb\u12ec\u0007"+ + "\u0018\u0000\u0000\u12ec\u12ed\u0007\r\u0000\u0000\u12ed\u12ee\u0007\u0013"+ + "\u0000\u0000\u12ee\u12ef\u0007\u000e\u0000\u0000\u12ef\u12f0\u0007\n\u0000"+ + "\u0000\u12f0\u12f1\u0007\f\u0000\u0000\u12f1\u12f2\u0007\u0016\u0000\u0000"+ + "\u12f2\u12f3\u0007\r\u0000\u0000\u12f3\u12f4\u0007\n\u0000\u0000\u12f4"+ + "\u12f5\u0007\t\u0000\u0000\u12f5\u03a4\u0001\u0000\u0000\u0000\u12f6\u12f7"+ + "\u0007\u0011\u0000\u0000\u12f7\u12f8\u0007\u0007\u0000\u0000\u12f8\u12f9"+ + "\u0007\u0018\u0000\u0000\u12f9\u12fa\u0007\u0016\u0000\u0000\u12fa\u12fb"+ + "\u0007\u0010\u0000\u0000\u12fb\u03a6\u0001\u0000\u0000\u0000\u12fc\u12fd"+ + "\u0007\t\u0000\u0000\u12fd\u12fe\u0007\u0016\u0000\u0000\u12fe\u12ff\u0007"+ + "\u0018\u0000\u0000\u12ff\u1300\u0007\u0018\u0000\u0000\u1300\u1301\u0007"+ + "\u0013\u0000\u0000\u1301\u1302\u0007\r\u0000\u0000\u1302\u1303\u0007\u0010"+ + "\u0000\u0000\u1303\u03a8\u0001\u0000\u0000\u0000\u1304\u1305\u0007\u0018"+ + "\u0000\u0000\u1305\u1306\u0007\u0005\u0000\u0000\u1306\u1307\u0007\r\u0000"+ + "\u0000\u1307\u1308\u0007\u0005\u0000\u0000\u1308\u1309\u0007\u0006\u0000"+ + "\u0000\u1309\u130a\u0007\u0006\u0000\u0000\u130a\u130b\u0007\n\u0000\u0000"+ + "\u130b\u130c\u0007\u0006\u0000\u0000\u130c\u03aa\u0001\u0000\u0000\u0000"+ + "\u130d\u130e\u0007\t\u0000\u0000\u130e\u130f\u0007\u001c\u0000\u0000\u130f"+ + "\u1310\u0007\u0006\u0000\u0000\u1310\u03ac\u0001\u0000\u0000\u0000\u1311"+ + "\u1312\u0007\f\u0000\u0000\u1312\u1313\u0007\n\u0000\u0000\u1313\u1314"+ + "\u0007\u0018\u0000\u0000\u1314\u1315\u0007\n\u0000\u0000\u1315\u1316\u0007"+ + "\u0007\u0000\u0000\u1316\u1317\u0007\f\u0000\u0000\u1317\u1318\u0007\t"+ + "\u0000\u0000\u1318\u03ae\u0001\u0000\u0000\u0000\u1319\u131a\u0007\u0013"+ + "\u0000\u0000\u131a\u131b\u0007\u001b\u0000\u0000\u131b\u131c\u0007\n\u0000"+ + "\u0000\u131c\u131d\u0007\r\u0000\u0000\u131d\u131e\u0007\r\u0000\u0000"+ + "\u131e\u131f\u0007\u0011\u0000\u0000\u131f\u1320\u0007\f\u0000\u0000\u1320"+ + "\u1321\u0007\u0011\u0000\u0000\u1321\u1322\u0007\u0007\u0000\u0000\u1322"+ + "\u1323\u0007\u0017\u0000\u0000\u1323\u03b0\u0001\u0000\u0000\u0000\u1324"+ + "\u1325\u0007\u000e\u0000\u0000\u1325\u1326\u0007\u0013\u0000\u0000\u1326"+ + "\u1327\u0007\u0007\u0000\u0000\u1327\u1328\u0007\u0019\u0000\u0000\u1328"+ + "\u1329\u0007\u0006\u0000\u0000\u1329\u132a\u0007\u0011\u0000\u0000\u132a"+ + "\u132b\u0007\u000e\u0000\u0000\u132b\u132c\u0007\u0010\u0000\u0000\u132c"+ + "\u03b2\u0001\u0000\u0000\u0000\u132d\u132e\u0007\t\u0000\u0000\u132e\u132f"+ + "\u0007\u0015\u0000\u0000\u132f\u1330\u0007\u0011\u0000\u0000\u1330\u1331"+ + "\u0007\u0018\u0000\u0000\u1331\u03b4\u0001\u0000\u0000\u0000\u1332\u1333"+ + "\u0007\u0006\u0000\u0000\u1333\u1334\u0007\u0013\u0000\u0000\u1334\u1335"+ + "\u0007\u000e\u0000\u0000\u1335\u1336\u0007\u0015\u0000\u0000\u1336\u1337"+ + "\u0007\n\u0000\u0000\u1337\u1338\u0007\f\u0000\u0000\u1338\u03b6\u0001"+ + "\u0000\u0000\u0000\u1339\u133a\u0007\u0010\u0000\u0000\u133a\u133b\u0007"+ + "\u0011\u0000\u0000\u133b\u133c\u0007\n\u0000\u0000\u133c\u133d\u0007\t"+ + "\u0000\u0000\u133d\u03b8\u0001\u0000\u0000\u0000\u133e\u133f\u0007\r\u0000"+ + "\u0000\u133f\u1340\u0007\u0013\u0000\u0000\u1340\u1341\u0007\u0006\u0000"+ + "\u0000\u1341\u1342\u0007\u0006\u0000\u0000\u1342\u1343\u0007\u0016\u0000"+ + "\u0000\u1343\u1344\u0007\u0018\u0000\u0000\u1344\u03ba\u0001\u0000\u0000"+ + "\u0000\u1345\u1346\u0007\u000e\u0000\u0000\u1346\u1347\u0007\u0016\u0000"+ + "\u0000\u1347\u1348\u0007\u0012\u0000\u0000\u1348\u1349\u0007\n\u0000\u0000"+ + "\u1349\u03bc\u0001\u0000\u0000\u0000\u134a\u134b\u0007\u0017\u0000\u0000"+ + "\u134b\u134c\u0007\r\u0000\u0000\u134c\u134d\u0007\u0013\u0000\u0000\u134d"+ + "\u134e\u0007\u0016\u0000\u0000\u134e\u134f\u0007\u0018\u0000\u0000\u134f"+ + "\u1350\u0007\u0011\u0000\u0000\u1350\u1351\u0007\u0007\u0000\u0000\u1351"+ + "\u1352\u0007\u0017\u0000\u0000\u1352\u03be\u0001\u0000\u0000\u0000\u1353"+ + "\u1354\u0007\t\u0000\u0000\u1354\u1355\u0007\n\u0000\u0000\u1355\u1356"+ + "\u0007\u0010\u0000\u0000\u1356\u1357\u0007\t\u0000\u0000\u1357\u03c0\u0001"+ + "\u0000\u0000\u0000\u1358\u1359\u0007\u0010\u0000\u0000\u1359\u135a\u0007"+ + "\u0005\u0000\u0000\u135a\u135b\u0007\u0012\u0000\u0000\u135b\u135c\u0007"+ + "\u0006\u0000\u0000\u135c\u135d\u0007\n\u0000\u0000\u135d\u135e\u0007\t"+ + "\u0000\u0000\u135e\u135f\u0007\u0005\u0000\u0000\u135f\u1360\u0007\u000f"+ + "\u0000\u0000\u1360\u1361\u0007\u0018\u0000\u0000\u1361\u1362\u0007\u0006"+ + "\u0000\u0000\u1362\u1363\u0007\n\u0000\u0000\u1363\u03c2\u0001\u0000\u0000"+ + "\u0000\u1364\u1365\u0007\u0013\u0000\u0000\u1365\u1366\u0007\r\u0000\u0000"+ + "\u1366\u1367\u0007\f\u0000\u0000\u1367\u1368\u0007\u0011\u0000\u0000\u1368"+ + "\u1369\u0007\u0007\u0000\u0000\u1369\u136a\u0007\u0005\u0000\u0000\u136a"+ + "\u136b\u0007\u0006\u0000\u0000\u136b\u136c\u0007\u0011\u0000\u0000\u136c"+ + "\u136d\u0007\u0010\u0000\u0000\u136d\u136e\u0007\b\u0000\u0000\u136e\u03c4"+ + "\u0001\u0000\u0000\u0000\u136f\u1370\u0007\u001a\u0000\u0000\u1370\u1371"+ + "\u0007\u000f\u0000\u0000\u1371\u1372\u0007\u0006\u0000\u0000\u1372\u1373"+ + "\u0007\u0010\u0000\u0000\u1373\u1374\u0007\u0005\u0000\u0000\u1374\u1375"+ + "\u0007\u0012\u0000\u0000\u1375\u1376\u0007\u0006\u0000\u0000\u1376\u1377"+ + "\u0007\n\u0000\u0000\u1377\u03c6\u0001\u0000\u0000\u0000\u1378\u1379\u0007"+ + "\u000e\u0000\u0000\u1379\u137a\u0007\u0013\u0000\u0000\u137a\u137b\u0007"+ + "\u0006\u0000\u0000\u137b\u137c\u0007\u0016\u0000\u0000\u137c\u137d\u0007"+ + "\u000f\u0000\u0000\u137d\u137e\u0007\u0007\u0000\u0000\u137e\u137f\u0007"+ + "\t\u0000\u0000\u137f\u03c8\u0001\u0000\u0000\u0000\u1380\u1381\u0007\u001a"+ + "\u0000\u0000\u1381\u1382\u0007\u000f\u0000\u0000\u1382\u1383\u0007\u0006"+ + "\u0000\u0000\u1383\u1384\u0007\u0007\u0000\u0000\u1384\u1385\u0007\u0005"+ + "\u0000\u0000\u1385\u1386\u0007\u000f\u0000\u0000\u1386\u1387\u0007\n\u0000"+ + "\u0000\u1387\u1388\u0007\t\u0000\u0000\u1388\u1389\u0007\u0018\u0000\u0000"+ + "\u1389\u138a\u0007\u0005\u0000\u0000\u138a\u138b\u0007\u000e\u0000\u0000"+ + "\u138b\u138c\u0007\n\u0000\u0000\u138c\u138d\u0007\t\u0000\u0000\u138d"+ + "\u03ca\u0001\u0000\u0000\u0000\u138e\u138f\u0007\r\u0000\u0000\u138f\u1390"+ + "\u0007\u0013\u0000\u0000\u1390\u1391\u0007\u001d\u0000\u0000\u1391\u1392"+ + "\u0007\u0010\u0000\u0000\u1392\u1393\u0007\b\u0000\u0000\u1393\u1394\u0007"+ + "\u0018\u0000\u0000\u1394\u1395\u0007\n\u0000\u0000\u1395\u03cc\u0001\u0000"+ + "\u0000\u0000\u1396\u1397\u0007\u0007\u0000\u0000\u1397\u1398\u0007\u0013"+ + "\u0000\u0000\u1398\u1399\u0007\r\u0000\u0000\u1399\u139a\u0007\u000f\u0000"+ + "\u0000\u139a\u139b\u0007\u0005\u0000\u0000\u139b\u139c\u0007\u0006\u0000"+ + "\u0000\u139c\u139d\u0007\u0011\u0000\u0000\u139d\u139e\u0007\u000b\u0000"+ + "\u0000\u139e\u139f\u0007\n\u0000\u0000\u139f\u13a0\u0007\f\u0000\u0000"+ + "\u13a0\u03ce\u0001\u0000\u0000\u0000\u13a1\u13a2\u0007\u001d\u0000\u0000"+ + "\u13a2\u13a3\u0007\u0011\u0000\u0000\u13a3\u13a4\u0007\u0010\u0000\u0000"+ + "\u13a4\u13a5\u0007\u0014\u0000\u0000\u13a5\u13a6\u0007\u0011\u0000\u0000"+ + "\u13a6\u13a7\u0007\u0007\u0000\u0000\u13a7\u03d0\u0001\u0000\u0000\u0000"+ + "\u13a8\u13a9\u0007\u0019\u0000\u0000\u13a9\u13aa\u0007\u0011\u0000\u0000"+ + "\u13aa\u13ab\u0007\u0006\u0000\u0000\u13ab\u13ac\u0007\u0010\u0000\u0000"+ + "\u13ac\u13ad\u0007\n\u0000\u0000\u13ad\u13ae\u0007\r\u0000\u0000\u13ae"+ + "\u03d2\u0001\u0000\u0000\u0000\u13af\u13b0\u0007\u0017\u0000\u0000\u13b0"+ + "\u13b1\u0007\r\u0000\u0000\u13b1\u13b2\u0007\u0013\u0000\u0000\u13b2\u13b3"+ + "\u0007\u0016\u0000\u0000\u13b3\u13b4\u0007\u0018\u0000\u0000\u13b4\u13b5"+ + "\u0007\t\u0000\u0000\u13b5\u03d4\u0001\u0000\u0000\u0000\u13b6\u13b7\u0007"+ + "\u0013\u0000\u0000\u13b7\u13b8\u0007\u0010\u0000\u0000\u13b8\u13b9\u0007"+ + "\u0014\u0000\u0000\u13b9\u13ba\u0007\n\u0000\u0000\u13ba\u13bb\u0007\r"+ + "\u0000\u0000\u13bb\u13bc\u0007\t\u0000\u0000\u13bc\u03d6\u0001\u0000\u0000"+ + "\u0000\u13bd\u13be\u0007\u0007\u0000\u0000\u13be\u13bf\u0007\u0019\u0000"+ + "\u0000\u13bf\u13c0\u0007\u000e\u0000\u0000\u13c0\u03d8\u0001\u0000\u0000"+ + "\u0000\u13c1\u13c2\u0007\u0007\u0000\u0000\u13c2\u13c3\u0007\u0019\u0000"+ + "\u0000\u13c3\u13c4\u0007\f\u0000\u0000\u13c4\u03da\u0001\u0000\u0000\u0000"+ + "\u13c5\u13c6\u0007\u0007\u0000\u0000\u13c6\u13c7\u0007\u0019\u0000\u0000"+ + "\u13c7\u13c8\u0007\u0015\u0000\u0000\u13c8\u13c9\u0007\u000e\u0000\u0000"+ + "\u13c9\u03dc\u0001\u0000\u0000\u0000\u13ca\u13cb\u0007\u0007\u0000\u0000"+ + "\u13cb\u13cc\u0007\u0019\u0000\u0000\u13cc\u13cd\u0007\u0015\u0000\u0000"+ + "\u13cd\u13ce\u0007\f\u0000\u0000\u13ce\u03de\u0001\u0000\u0000\u0000\u13cf"+ + "\u13d0\u0007\u0016\u0000\u0000\u13d0\u13d1\u0007\n\u0000\u0000\u13d1\u13d2"+ + "\u0007\t\u0000\u0000\u13d2\u13d3\u0007\u000e\u0000\u0000\u13d3\u13d4\u0007"+ + "\u0005\u0000\u0000\u13d4\u13d5\u0007\u0018\u0000\u0000\u13d5\u13d6\u0007"+ + "\n\u0000\u0000\u13d6\u03e0\u0001\u0000\u0000\u0000\u13d7\u13d8\u0007\u001b"+ + "\u0000\u0000\u13d8\u13d9\u0007\u0011\u0000\u0000\u13d9\u13da\u0007\n\u0000"+ + "\u0000\u13da\u13db\u0007\u001d\u0000\u0000\u13db\u13dc\u0007\t\u0000\u0000"+ + "\u13dc\u03e2\u0001\u0000\u0000\u0000\u13dd\u13de\u0007\u0007\u0000\u0000"+ + "\u13de\u13df\u0007\u0013\u0000\u0000\u13df\u13e0\u0007\r\u0000\u0000\u13e0"+ + "\u13e1\u0007\u000f\u0000\u0000\u13e1\u13e2\u0007\u0005\u0000\u0000\u13e2"+ + "\u13e3\u0007\u0006\u0000\u0000\u13e3\u13e4\u0007\u0011\u0000\u0000\u13e4"+ + "\u13e5\u0007\u000b\u0000\u0000\u13e5\u13e6\u0007\n\u0000\u0000\u13e6\u03e4"+ + "\u0001\u0000\u0000\u0000\u13e7\u13e8\u0007\f\u0000\u0000\u13e8\u13e9\u0007"+ + "\u0016\u0000\u0000\u13e9\u13ea\u0007\u000f\u0000\u0000\u13ea\u13eb\u0007"+ + "\u0018\u0000\u0000\u13eb\u03e6\u0001\u0000\u0000\u0000\u13ec\u13ed\u0007"+ + "\u0018\u0000\u0000\u13ed\u13ee\u0007\r\u0000\u0000\u13ee\u13ef\u0007\u0011"+ + "\u0000\u0000\u13ef\u13f0\u0007\u0007\u0000\u0000\u13f0\u13f1\u0007\u0010"+ + "\u0000\u0000\u13f1\u13f2\u0005_\u0000\u0000\u13f2\u13f3\u0007\t\u0000"+ + "\u0000\u13f3\u13f4\u0007\u0010\u0000\u0000\u13f4\u13f5\u0007\r\u0000\u0000"+ + "\u13f5\u13f6\u0007\u0011\u0000\u0000\u13f6\u13f7\u0007\u000e\u0000\u0000"+ + "\u13f7\u13f8\u0007\u0010\u0000\u0000\u13f8\u13f9\u0005_\u0000\u0000\u13f9"+ + "\u13fa\u0007\u0018\u0000\u0000\u13fa\u13fb\u0007\u0005\u0000\u0000\u13fb"+ + "\u13fc\u0007\r\u0000\u0000\u13fc\u13fd\u0007\u0005\u0000\u0000\u13fd\u13fe"+ + "\u0007\u000f\u0000\u0000\u13fe\u13ff\u0007\t\u0000\u0000\u13ff\u03e8\u0001"+ + "\u0000\u0000\u0000\u1400\u1401\u0007\u001b\u0000\u0000\u1401\u1402\u0007"+ + "\u0005\u0000\u0000\u1402\u1403\u0007\r\u0000\u0000\u1403\u1404\u0007\u0011"+ + "\u0000\u0000\u1404\u1405\u0007\u0005\u0000\u0000\u1405\u1406\u0007\u0012"+ + "\u0000\u0000\u1406\u1407\u0007\u0006\u0000\u0000\u1407\u1408\u0007\n\u0000"+ + "\u0000\u1408\u1409\u0005_\u0000\u0000\u1409\u140a\u0007\u000e\u0000\u0000"+ + "\u140a\u140b\u0007\u0013\u0000\u0000\u140b\u140c\u0007\u0007\u0000\u0000"+ + "\u140c\u140d\u0007\u0019\u0000\u0000\u140d\u140e\u0007\u0006\u0000\u0000"+ + "\u140e\u140f\u0007\u0011\u0000\u0000\u140f\u1410\u0007\u000e\u0000\u0000"+ + "\u1410\u1411\u0007\u0010\u0000\u0000\u1411\u03ea\u0001\u0000\u0000\u0000"+ + "\u1412\u1413\u0007\n\u0000\u0000\u1413\u1414\u0007\r\u0000\u0000\u1414"+ + "\u1415\u0007\r\u0000\u0000\u1415\u1416\u0007\u0013\u0000\u0000\u1416\u1417"+ + "\u0007\r\u0000\u0000\u1417\u03ec\u0001\u0000\u0000\u0000\u1418\u1419\u0007"+ + "\u0016\u0000\u0000\u1419\u141a\u0007\t\u0000\u0000\u141a\u141b\u0007\n"+ + "\u0000\u0000\u141b\u141c\u0005_\u0000\u0000\u141c\u141d\u0007\u001b\u0000"+ + "\u0000\u141d\u141e\u0007\u0005\u0000\u0000\u141e\u141f\u0007\r\u0000\u0000"+ + "\u141f\u1420\u0007\u0011\u0000\u0000\u1420\u1421\u0007\u0005\u0000\u0000"+ + "\u1421\u1422\u0007\u0012\u0000\u0000\u1422\u1423\u0007\u0006\u0000\u0000"+ + "\u1423\u1424\u0007\n\u0000\u0000\u1424\u03ee\u0001\u0000\u0000\u0000\u1425"+ + "\u1426\u0007\u0016\u0000\u0000\u1426\u1427\u0007\t\u0000\u0000\u1427\u1428"+ + "\u0007\n\u0000\u0000\u1428\u1429\u0005_\u0000\u0000\u1429\u142a\u0007"+ + "\u000e\u0000\u0000\u142a\u142b\u0007\u0013\u0000\u0000\u142b\u142c\u0007"+ + "\u0006\u0000\u0000\u142c\u142d\u0007\u0016\u0000\u0000\u142d\u142e\u0007"+ + "\u000f\u0000\u0000\u142e\u142f\u0007\u0007\u0000\u0000\u142f\u03f0\u0001"+ + "\u0000\u0000\u0000\u1430\u1431\u0007\u0005\u0000\u0000\u1431\u1432\u0007"+ + "\u0006\u0000\u0000\u1432\u1433\u0007\u0011\u0000\u0000\u1433\u1434\u0007"+ + "\u0005\u0000\u0000\u1434\u1435\u0007\t\u0000\u0000\u1435\u03f2\u0001\u0000"+ + "\u0000\u0000\u1436\u1437\u0007\u000e\u0000\u0000\u1437\u1438\u0007\u0013"+ + "\u0000\u0000\u1438\u1439\u0007\u0007\u0000\u0000\u1439\u143a\u0007\t\u0000"+ + "\u0000\u143a\u143b\u0007\u0010\u0000\u0000\u143b\u143c\u0007\u0005\u0000"+ + "\u0000\u143c\u143d\u0007\u0007\u0000\u0000\u143d\u143e\u0007\u0010\u0000"+ + "\u0000\u143e\u03f4\u0001\u0000\u0000\u0000\u143f\u1440\u0007\u0018\u0000"+ + "\u0000\u1440\u1441\u0007\n\u0000\u0000\u1441\u1442\u0007\r\u0000\u0000"+ + "\u1442\u1443\u0007\u0019\u0000\u0000\u1443\u1444\u0007\u0013\u0000\u0000"+ + "\u1444\u1445\u0007\r\u0000\u0000\u1445\u1446\u0007\u000f\u0000\u0000\u1446"+ + "\u03f6\u0001\u0000\u0000\u0000\u1447\u1448\u0007\u0017\u0000\u0000\u1448"+ + "\u1449\u0007\n\u0000\u0000\u1449\u144a\u0007\u0010\u0000\u0000\u144a\u03f8"+ + "\u0001\u0000\u0000\u0000\u144b\u144c\u0007\f\u0000\u0000\u144c\u144d\u0007"+ + "\u0011\u0000\u0000\u144d\u144e\u0007\u0005\u0000\u0000\u144e\u144f\u0007"+ + "\u0017\u0000\u0000\u144f\u1450\u0007\u0007\u0000\u0000\u1450\u1451\u0007"+ + "\u0013\u0000\u0000\u1451\u1452\u0007\t\u0000\u0000\u1452\u1453\u0007\u0010"+ + "\u0000\u0000\u1453\u1454\u0007\u0011\u0000\u0000\u1454\u1455\u0007\u000e"+ + "\u0000\u0000\u1455\u1456\u0007\t\u0000\u0000\u1456\u03fa\u0001\u0000\u0000"+ + "\u0000\u1457\u1458\u0007\t\u0000\u0000\u1458\u1459\u0007\u0010\u0000\u0000"+ + "\u1459\u145a\u0007\u0005\u0000\u0000\u145a\u145b\u0007\u000e\u0000\u0000"+ + "\u145b\u145c\u0007\u0015\u0000\u0000\u145c\u145d\u0007\n\u0000\u0000\u145d"+ + "\u145e\u0007\f\u0000\u0000\u145e\u03fc\u0001\u0000\u0000\u0000\u145f\u1460"+ + "\u0007\n\u0000\u0000\u1460\u1461\u0007\u0006\u0000\u0000\u1461\u1462\u0007"+ + "\t\u0000\u0000\u1462\u1463\u0007\u0011\u0000\u0000\u1463\u1464\u0007\u0019"+ + "\u0000\u0000\u1464\u03fe\u0001\u0000\u0000\u0000\u1465\u1466\u0007\u001d"+ + "\u0000\u0000\u1466\u1467\u0007\u0014\u0000\u0000\u1467\u1468\u0007\u0011"+ + "\u0000\u0000\u1468\u1469\u0007\u0006\u0000\u0000\u1469\u146a\u0007\n\u0000"+ + "\u0000\u146a\u0400\u0001\u0000\u0000\u0000\u146b\u146c\u0007\r\u0000\u0000"+ + "\u146c\u146d\u0007\n\u0000\u0000\u146d\u146e\u0007\u001b\u0000\u0000\u146e"+ + "\u146f\u0007\n\u0000\u0000\u146f\u1470\u0007\r\u0000\u0000\u1470\u1471"+ + "\u0007\t\u0000\u0000\u1471\u1472\u0007\n\u0000\u0000\u1472\u0402\u0001"+ + "\u0000\u0000\u0000\u1473\u1474\u0007\u0019\u0000\u0000\u1474\u1475\u0007"+ + "\u0013\u0000\u0000\u1475\u1476\u0007\r\u0000\u0000\u1476\u1477\u0007\n"+ + "\u0000\u0000\u1477\u1478\u0007\u0005\u0000\u0000\u1478\u1479\u0007\u000e"+ + "\u0000\u0000\u1479\u147a\u0007\u0014\u0000\u0000\u147a\u0404\u0001\u0000"+ + "\u0000\u0000\u147b\u147c\u0007\t\u0000\u0000\u147c\u147d\u0007\u0006\u0000"+ + "\u0000\u147d\u147e\u0007\u0011\u0000\u0000\u147e\u147f\u0007\u000e\u0000"+ + "\u0000\u147f\u1480\u0007\n\u0000\u0000\u1480\u0406\u0001\u0000\u0000\u0000"+ + "\u1481\u1482\u0007\n\u0000\u0000\u1482\u1483\u0007\u001a\u0000\u0000\u1483"+ + "\u1484\u0007\u0011\u0000\u0000\u1484\u1485\u0007\u0010\u0000\u0000\u1485"+ + "\u0408\u0001\u0000\u0000\u0000\u1486\u1487\u0007\r\u0000\u0000\u1487\u1488"+ + "\u0007\n\u0000\u0000\u1488\u1489\u0007\u0010\u0000\u0000\u1489\u148a\u0007"+ + "\u0016\u0000\u0000\u148a\u148b\u0007\r\u0000\u0000\u148b\u148c\u0007\u0007"+ + "\u0000\u0000\u148c\u040a\u0001\u0000\u0000\u0000\u148d\u148e\u0007\u001c"+ + "\u0000\u0000\u148e\u148f\u0007\u0016\u0000\u0000\u148f\u1490\u0007\n\u0000"+ + "\u0000\u1490\u1491\u0007\r\u0000\u0000\u1491\u1492\u0007\b\u0000\u0000"+ + "\u1492\u040c\u0001\u0000\u0000\u0000\u1493\u1494\u0007\r\u0000\u0000\u1494"+ + "\u1495\u0007\u0005\u0000\u0000\u1495\u1496\u0007\u0011\u0000\u0000\u1496"+ + "\u1497\u0007\t\u0000\u0000\u1497\u1498\u0007\n\u0000\u0000\u1498\u040e"+ + "\u0001\u0000\u0000\u0000\u1499\u149a\u0007\t\u0000\u0000\u149a\u149b\u0007"+ + "\u001c\u0000\u0000\u149b\u149c\u0007\u0006\u0000\u0000\u149c\u149d\u0007"+ + "\t\u0000\u0000\u149d\u149e\u0007\u0010\u0000\u0000\u149e\u149f\u0007\u0005"+ + "\u0000\u0000\u149f\u14a0\u0007\u0010\u0000\u0000\u14a0\u14a1\u0007\n\u0000"+ + "\u0000\u14a1\u0410\u0001\u0000\u0000\u0000\u14a2\u14a3\u0007\f\u0000\u0000"+ + "\u14a3\u14a4\u0007\n\u0000\u0000\u14a4\u14a5\u0007\u0012\u0000\u0000\u14a5"+ + "\u14a6\u0007\u0016\u0000\u0000\u14a6\u14a7\u0007\u0017\u0000\u0000\u14a7"+ + "\u0412\u0001\u0000\u0000\u0000\u14a8\u14a9\u0007\u0006\u0000\u0000\u14a9"+ + "\u14aa\u0007\u0013\u0000\u0000\u14aa\u14ab\u0007\u0017\u0000\u0000\u14ab"+ + "\u0414\u0001\u0000\u0000\u0000\u14ac\u14ad\u0007\u0011\u0000\u0000\u14ad"+ + "\u14ae\u0007\u0007\u0000\u0000\u14ae\u14af\u0007\u0019\u0000\u0000\u14af"+ + "\u14b0\u0007\u0013\u0000\u0000\u14b0\u0416\u0001\u0000\u0000\u0000\u14b1"+ + "\u14b2\u0007\u0007\u0000\u0000\u14b2\u14b3\u0007\u0013\u0000\u0000\u14b3"+ + "\u14b4\u0007\u0010\u0000\u0000\u14b4\u14b5\u0007\u0011\u0000\u0000\u14b5"+ + "\u14b6\u0007\u000e\u0000\u0000\u14b6\u14b7\u0007\n\u0000\u0000\u14b7\u0418"+ + "\u0001\u0000\u0000\u0000\u14b8\u14b9\u0007\u001d\u0000\u0000\u14b9\u14ba"+ + "\u0007\u0005\u0000\u0000\u14ba\u14bb\u0007\r\u0000\u0000\u14bb\u14bc\u0007"+ + "\u0007\u0000\u0000\u14bc\u14bd\u0007\u0011\u0000\u0000\u14bd\u14be\u0007"+ + "\u0007\u0000\u0000\u14be\u14bf\u0007\u0017\u0000\u0000\u14bf\u041a\u0001"+ + "\u0000\u0000\u0000\u14c0\u14c1\u0007\n\u0000\u0000\u14c1\u14c2\u0007\u001a"+ + "\u0000\u0000\u14c2\u14c3\u0007\u000e\u0000\u0000\u14c3\u14c4\u0007\n\u0000"+ + "\u0000\u14c4\u14c5\u0007\u0018\u0000\u0000\u14c5\u14c6\u0007\u0010\u0000"+ + "\u0000\u14c6\u14c7\u0007\u0011\u0000\u0000\u14c7\u14c8\u0007\u0013\u0000"+ + "\u0000\u14c8\u14c9\u0007\u0007\u0000\u0000\u14c9\u041c\u0001\u0000\u0000"+ + "\u0000\u14ca\u14cb\u0007\u0005\u0000\u0000\u14cb\u14cc\u0007\t\u0000\u0000"+ + "\u14cc\u14cd\u0007\t\u0000\u0000\u14cd\u14ce\u0007\n\u0000\u0000\u14ce"+ + "\u14cf\u0007\r\u0000\u0000\u14cf\u14d0\u0007\u0010\u0000\u0000\u14d0\u041e"+ + "\u0001\u0000\u0000\u0000\u14d1\u14d2\u0007\u0006\u0000\u0000\u14d2\u14d3"+ + "\u0007\u0013\u0000\u0000\u14d3\u14d4\u0007\u0013\u0000\u0000\u14d4\u14d5"+ + "\u0007\u0018\u0000\u0000\u14d5\u0420\u0001\u0000\u0000\u0000\u14d6\u14d7"+ + "\u0007\u0013\u0000\u0000\u14d7\u14d8\u0007\u0018\u0000\u0000\u14d8\u14d9"+ + "\u0007\n\u0000\u0000\u14d9\u14da\u0007\u0007\u0000\u0000\u14da\u0422\u0001"+ + "\u0000\u0000\u0000\u14db\u14dc\u0007\u0010\u0000\u0000\u14dc\u14dd\u0007"+ + "\u0013\u0000\u0000\u14dd\u14de\u0007\u0018\u0000\u0000\u14de\u0424\u0001"+ + "\u0000\u0000\u0000\u14df\u14e0\u0007\u0005\u0000\u0000\u14e0\u14e1\u0007"+ + "\u0012\u0000\u0000\u14e1\u14e2\u0007\t\u0000\u0000\u14e2\u0426\u0001\u0000"+ + "\u0000\u0000\u14e3\u14e4\u0007\u000e\u0000\u0000\u14e4\u14e5\u0007\u0012"+ + "\u0000\u0000\u14e5\u14e6\u0007\r\u0000\u0000\u14e6\u14e7\u0007\u0010\u0000"+ + "\u0000\u14e7\u0428\u0001\u0000\u0000\u0000\u14e8\u14e9\u0007\u000e\u0000"+ + "\u0000\u14e9\u14ea\u0007\n\u0000\u0000\u14ea\u14eb\u0007\u0011\u0000\u0000"+ + "\u14eb\u14ec\u0007\u0006\u0000\u0000\u14ec\u042a\u0001\u0000\u0000\u0000"+ + "\u14ed\u14ee\u0007\u000e\u0000\u0000\u14ee\u14ef\u0007\n\u0000\u0000\u14ef"+ + "\u14f0\u0007\u0011\u0000\u0000\u14f0\u14f1\u0007\u0006\u0000\u0000\u14f1"+ + "\u14f2\u0007\u0011\u0000\u0000\u14f2\u14f3\u0007\u0007\u0000\u0000\u14f3"+ + "\u14f4\u0007\u0017\u0000\u0000\u14f4\u042c\u0001\u0000\u0000\u0000\u14f5"+ + "\u14f6\u0007\f\u0000\u0000\u14f6\u14f7\u0007\n\u0000\u0000\u14f7\u14f8"+ + "\u0007\u0017\u0000\u0000\u14f8\u14f9\u0007\r\u0000\u0000\u14f9\u14fa\u0007"+ + "\n\u0000\u0000\u14fa\u14fb\u0007\n\u0000\u0000\u14fb\u14fc\u0007\t\u0000"+ + "\u0000\u14fc\u042e\u0001\u0000\u0000\u0000\u14fd\u14fe\u0007\f\u0000\u0000"+ + "\u14fe\u14ff\u0007\u0011\u0000\u0000\u14ff\u1500\u0007\u001b\u0000\u0000"+ + "\u1500\u0430\u0001\u0000\u0000\u0000\u1501\u1502\u0007\n\u0000\u0000\u1502"+ + "\u1503\u0007\u001a\u0000\u0000\u1503\u1504\u0007\u0018\u0000\u0000\u1504"+ + "\u0432\u0001\u0000\u0000\u0000\u1505\u1506\u0007\u0019\u0000\u0000\u1506"+ + "\u1507\u0007\u0005\u0000\u0000\u1507\u1508\u0007\u000e\u0000\u0000\u1508"+ + "\u1509\u0007\u0010\u0000\u0000\u1509\u150a\u0007\u0013\u0000\u0000\u150a"+ + "\u150b\u0007\r\u0000\u0000\u150b\u150c\u0007\u0011\u0000\u0000\u150c\u150d"+ + "\u0007\u0005\u0000\u0000\u150d\u150e\u0007\u0006\u0000\u0000\u150e\u0434"+ + "\u0001\u0000\u0000\u0000\u150f\u1510\u0007\u0019\u0000\u0000\u1510\u1511"+ + "\u0007\u0006\u0000\u0000\u1511\u1512\u0007\u0013\u0000\u0000\u1512\u1513"+ + "\u0007\u0013\u0000\u0000\u1513\u1514\u0007\r\u0000\u0000\u1514\u0436\u0001"+ + "\u0000\u0000\u0000\u1515\u1516\u0007\u0017\u0000\u0000\u1516\u1517\u0007"+ + "\u000e\u0000\u0000\u1517\u1518\u0007\f\u0000\u0000\u1518\u0438\u0001\u0000"+ + "\u0000\u0000\u1519\u151a\u0007\u0006\u0000\u0000\u151a\u151b\u0007\u000e"+ + "\u0000\u0000\u151b\u151c\u0007\u000f\u0000\u0000\u151c\u043a\u0001\u0000"+ + "\u0000\u0000\u151d\u151e\u0007\u0006\u0000\u0000\u151e\u151f\u0007\u0007"+ + "\u0000\u0000\u151f\u043c\u0001\u0000\u0000\u0000\u1520\u1521\u0007\u0006"+ + "\u0000\u0000\u1521\u1522\u0007\u0013\u0000\u0000\u1522\u1523\u0007\u0017"+ + "\u0000\u0000\u1523\u1524\u00051\u0000\u0000\u1524\u1525\u00050\u0000\u0000"+ + "\u1525\u043e\u0001\u0000\u0000\u0000\u1526\u1527\u0007\u000f\u0000\u0000"+ + "\u1527\u1528\u0007\u0011\u0000\u0000\u1528\u1529\u0007\u0007\u0000\u0000"+ + "\u1529\u152a\u0005_\u0000\u0000\u152a\u152b\u0007\t\u0000\u0000\u152b"+ + "\u152c\u0007\u000e\u0000\u0000\u152c\u152d\u0007\u0005\u0000\u0000\u152d"+ + "\u152e\u0007\u0006\u0000\u0000\u152e\u152f\u0007\n\u0000\u0000\u152f\u0440"+ + "\u0001\u0000\u0000\u0000\u1530\u1531\u0007\u000f\u0000\u0000\u1531\u1532"+ + "\u0007\u0013\u0000\u0000\u1532\u1533\u0007\f\u0000\u0000\u1533\u0442\u0001"+ + "\u0000\u0000\u0000\u1534\u1535\u0007\u0018\u0000\u0000\u1535\u1536\u0007"+ + "\u0011\u0000\u0000\u1536\u0444\u0001\u0000\u0000\u0000\u1537\u1538\u0007"+ + "\u0018\u0000\u0000\u1538\u1539\u0007\u0013\u0000\u0000\u1539\u153a\u0007"+ + "\u001d\u0000\u0000\u153a\u153b\u0007\n\u0000\u0000\u153b\u153c\u0007\r"+ + "\u0000\u0000\u153c\u0446\u0001\u0000\u0000\u0000\u153d\u153e\u0007\r\u0000"+ + "\u0000\u153e\u153f\u0007\u0005\u0000\u0000\u153f\u1540\u0007\f\u0000\u0000"+ + "\u1540\u1541\u0007\u0011\u0000\u0000\u1541\u1542\u0007\u0005\u0000\u0000"+ + "\u1542\u1543\u0007\u0007\u0000\u0000\u1543\u1544\u0007\t\u0000\u0000\u1544"+ + "\u0448\u0001\u0000\u0000\u0000\u1545\u1546\u0007\r\u0000\u0000\u1546\u1547"+ + "\u0007\u0013\u0000\u0000\u1547\u1548\u0007\u0016\u0000\u0000\u1548\u1549"+ + "\u0007\u0007\u0000\u0000\u1549\u154a\u0007\f\u0000\u0000\u154a\u044a\u0001"+ + "\u0000\u0000\u0000\u154b\u154c\u0007\t\u0000\u0000\u154c\u154d\u0007\u000e"+ + "\u0000\u0000\u154d\u154e\u0007\u0005\u0000\u0000\u154e\u154f\u0007\u0006"+ + "\u0000\u0000\u154f\u1550\u0007\n\u0000\u0000\u1550\u044c\u0001\u0000\u0000"+ + "\u0000\u1551\u1552\u0007\t\u0000\u0000\u1552\u1553\u0007\u0011\u0000\u0000"+ + "\u1553\u1554\u0007\u0017\u0000\u0000\u1554\u1555\u0007\u0007\u0000\u0000"+ + "\u1555\u044e\u0001\u0000\u0000\u0000\u1556\u1557\u0007\t\u0000\u0000\u1557"+ + "\u1558\u0007\u001c\u0000\u0000\u1558\u1559\u0007\r\u0000\u0000\u1559\u155a"+ + "\u0007\u0010\u0000\u0000\u155a\u0450\u0001\u0000\u0000\u0000\u155b\u155c"+ + "\u0007\u0010\u0000\u0000\u155c\u155d\u0007\r\u0000\u0000\u155d\u155e\u0007"+ + "\u0011\u0000\u0000\u155e\u155f\u0007\u000f\u0000\u0000\u155f\u1560\u0005"+ + "_\u0000\u0000\u1560\u1561\u0007\t\u0000\u0000\u1561\u1562\u0007\u000e"+ + "\u0000\u0000\u1562\u1563\u0007\u0005\u0000\u0000\u1563\u1564\u0007\u0006"+ + "\u0000\u0000\u1564\u1565\u0007\n\u0000\u0000\u1565\u0452\u0001\u0000\u0000"+ + "\u0000\u1566\u1567\u0007\u0010\u0000\u0000\u1567\u1568\u0007\r\u0000\u0000"+ + "\u1568\u1569\u0007\u0016\u0000\u0000\u1569\u156a\u0007\u0007\u0000\u0000"+ + "\u156a\u156b\u0007\u000e\u0000\u0000\u156b\u0454\u0001\u0000\u0000\u0000"+ + "\u156c\u156d\u0007\u001d\u0000\u0000\u156d\u156e\u0007\u0011\u0000\u0000"+ + "\u156e\u156f\u0007\f\u0000\u0000\u156f\u1570\u0007\u0010\u0000\u0000\u1570"+ + "\u1571\u0007\u0014\u0000\u0000\u1571\u1572\u0005_\u0000\u0000\u1572\u1573"+ + "\u0007\u0012\u0000\u0000\u1573\u1574\u0007\u0016\u0000\u0000\u1574\u1575"+ + "\u0007\u000e\u0000\u0000\u1575\u1576\u0007\u0015\u0000\u0000\u1576\u1577"+ + "\u0007\n\u0000\u0000\u1577\u1578\u0007\u0010\u0000\u0000\u1578\u0456\u0001"+ + "\u0000\u0000\u0000\u1579\u157a\u0007\r\u0000\u0000\u157a\u157b\u0007\u0005"+ + "\u0000\u0000\u157b\u157c\u0007\u0007\u0000\u0000\u157c\u157d\u0007\f\u0000"+ + "\u0000\u157d\u157e\u0007\u0013\u0000\u0000\u157e\u157f\u0007\u000f\u0000"+ + "\u0000\u157f\u0458\u0001\u0000\u0000\u0000\u1580\u1581\u0007\t\u0000\u0000"+ + "\u1581\u1582\u0007\n\u0000\u0000\u1582\u1583\u0007\u0010\u0000\u0000\u1583"+ + "\u1584\u0007\t\u0000\u0000\u1584\u1585\u0007\n\u0000\u0000\u1585\u1586"+ + "\u0007\n\u0000\u0000\u1586\u1587\u0007\f\u0000\u0000\u1587\u045a\u0001"+ + "\u0000\u0000\u0000\u1588\u1589\u0007\u0005\u0000\u0000\u1589\u158a\u0007"+ + "\u000e\u0000\u0000\u158a\u158b\u0007\u0013\u0000\u0000\u158b\u158c\u0007"+ + "\t\u0000\u0000\u158c\u045c\u0001\u0000\u0000\u0000\u158d\u158e\u0007\u0005"+ + "\u0000\u0000\u158e\u158f\u0007\u000e\u0000\u0000\u158f\u1590\u0007\u0013"+ + "\u0000\u0000\u1590\u1591\u0007\t\u0000\u0000\u1591\u1592\u0007\f\u0000"+ + "\u0000\u1592\u045e\u0001\u0000\u0000\u0000\u1593\u1594\u0007\u0005\u0000"+ + "\u0000\u1594\u1595\u0007\t\u0000\u0000\u1595\u1596\u0007\u0011\u0000\u0000"+ + "\u1596\u1597\u0007\u0007\u0000\u0000\u1597\u0460\u0001\u0000\u0000\u0000"+ + "\u1598\u1599\u0007\u0005\u0000\u0000\u1599\u159a\u0007\t\u0000\u0000\u159a"+ + "\u159b\u0007\u0011\u0000\u0000\u159b\u159c\u0007\u0007\u0000\u0000\u159c"+ + "\u159d\u0007\f\u0000\u0000\u159d\u0462\u0001\u0000\u0000\u0000\u159e\u159f"+ + "\u0007\u0005\u0000\u0000\u159f\u15a0\u0007\u0010\u0000\u0000\u15a0\u15a1"+ + "\u0007\u0005\u0000\u0000\u15a1\u15a2\u0007\u0007\u0000\u0000\u15a2\u0464"+ + "\u0001\u0000\u0000\u0000\u15a3\u15a4\u0007\u0005\u0000\u0000\u15a4\u15a5"+ + "\u0007\u0010\u0000\u0000\u15a5\u15a6\u0007\u0005\u0000\u0000\u15a6\u15a7"+ + "\u0007\u0007\u0000\u0000\u15a7\u15a8\u0007\f\u0000\u0000\u15a8\u0466\u0001"+ + "\u0000\u0000\u0000\u15a9\u15aa\u0007\u0005\u0000\u0000\u15aa\u15ab\u0007"+ + "\u0010\u0000\u0000\u15ab\u15ac\u0007\u0005\u0000\u0000\u15ac\u15ad\u0007"+ + "\u0007\u0000\u0000\u15ad\u15ae\u00052\u0000\u0000\u15ae\u0468\u0001\u0000"+ + "\u0000\u0000\u15af\u15b0\u0007\u0005\u0000\u0000\u15b0\u15b1\u0007\u0010"+ + "\u0000\u0000\u15b1\u15b2\u0007\u0005\u0000\u0000\u15b2\u15b3\u0007\u0007"+ + "\u0000\u0000\u15b3\u15b4\u00052\u0000\u0000\u15b4\u15b5\u0007\f\u0000"+ + "\u0000\u15b5\u046a\u0001\u0000\u0000\u0000\u15b6\u15b7\u0007\u000e\u0000"+ + "\u0000\u15b7\u15b8\u0007\u0013\u0000\u0000\u15b8\u15b9\u0007\t\u0000\u0000"+ + "\u15b9\u046c\u0001\u0000\u0000\u0000\u15ba\u15bb\u0007\u000e\u0000\u0000"+ + "\u15bb\u15bc\u0007\u0013\u0000\u0000\u15bc\u15bd\u0007\t\u0000\u0000\u15bd"+ + "\u15be\u0007\f\u0000\u0000\u15be\u046e\u0001\u0000\u0000\u0000\u15bf\u15c0"+ + "\u0007\u000e\u0000\u0000\u15c0\u15c1\u0007\u0013\u0000\u0000\u15c1\u15c2"+ + "\u0007\u0010\u0000\u0000\u15c2\u0470\u0001\u0000\u0000\u0000\u15c3\u15c4"+ + "\u0007\u000e\u0000\u0000\u15c4\u15c5\u0007\u0013\u0000\u0000\u15c5\u15c6"+ + "\u0007\u0010\u0000\u0000\u15c6\u15c7\u0007\f\u0000\u0000\u15c7\u0472\u0001"+ + "\u0000\u0000\u0000\u15c8\u15c9\u0007\t\u0000\u0000\u15c9\u15ca\u0007\u0011"+ + "\u0000\u0000\u15ca\u15cb\u0007\u0007\u0000\u0000\u15cb\u0474\u0001\u0000"+ + "\u0000\u0000\u15cc\u15cd\u0007\t\u0000\u0000\u15cd\u15ce\u0007\u0011\u0000"+ + "\u0000\u15ce\u15cf\u0007\u0007\u0000\u0000\u15cf\u15d0\u0007\f\u0000\u0000"+ + "\u15d0\u0476\u0001\u0000\u0000\u0000\u15d1\u15d2\u0007\u0010\u0000\u0000"+ + "\u15d2\u15d3\u0007\u0005\u0000\u0000\u15d3\u15d4\u0007\u0007\u0000\u0000"+ + "\u15d4\u0478\u0001\u0000\u0000\u0000\u15d5\u15d6\u0007\u0010\u0000\u0000"+ + "\u15d6\u15d7\u0007\u0005\u0000\u0000\u15d7\u15d8\u0007\u0007\u0000\u0000"+ + "\u15d8\u15d9\u0007\f\u0000\u0000\u15d9\u047a\u0001\u0000\u0000\u0000\u15da"+ + "\u15db\u0007\t\u0000\u0000\u15db\u15dc\u0007\u0011\u0000\u0000\u15dc\u15dd"+ + "\u0007\u0007\u0000\u0000\u15dd\u15de\u0007\u0014\u0000\u0000\u15de\u047c"+ + "\u0001\u0000\u0000\u0000\u15df\u15e0\u0007\u000e\u0000\u0000\u15e0\u15e1"+ + "\u0007\u0013\u0000\u0000\u15e1\u15e2\u0007\t\u0000\u0000\u15e2\u15e3\u0007"+ + "\u0014\u0000\u0000\u15e3\u047e\u0001\u0000\u0000\u0000\u15e4\u15e5\u0007"+ + "\u0010\u0000\u0000\u15e5\u15e6\u0007\u0005\u0000\u0000\u15e6\u15e7\u0007"+ + "\u0007\u0000\u0000\u15e7\u15e8\u0007\u0014\u0000\u0000\u15e8\u0480\u0001"+ + "\u0000\u0000\u0000\u15e9\u15ea\u0007\u0005\u0000\u0000\u15ea\u15eb\u0007"+ + "\t\u0000\u0000\u15eb\u15ec\u0007\u0011\u0000\u0000\u15ec\u15ed\u0007\u0007"+ + "\u0000\u0000\u15ed\u15ee\u0007\u0014\u0000\u0000\u15ee\u0482\u0001\u0000"+ + "\u0000\u0000\u15ef\u15f0\u0007\u0005\u0000\u0000\u15f0\u15f1\u0007\u000e"+ + "\u0000\u0000\u15f1\u15f2\u0007\u0013\u0000\u0000\u15f2\u15f3\u0007\t\u0000"+ + "\u0000\u15f3\u15f4\u0007\u0014\u0000\u0000\u15f4\u0484\u0001\u0000\u0000"+ + "\u0000\u15f5\u15f6\u0007\u0005\u0000\u0000\u15f6\u15f7\u0007\u0010\u0000"+ + "\u0000\u15f7\u15f8\u0007\u0005\u0000\u0000\u15f8\u15f9\u0007\u0007\u0000"+ + "\u0000\u15f9\u15fa\u0007\u0014\u0000\u0000\u15fa\u0486\u0001\u0000\u0000"+ + "\u0000\u15fb\u15fc\u0007\u0012\u0000\u0000\u15fc\u15fd\u0007\u0011\u0000"+ + "\u0000\u15fd\u15fe\u0007\u0010\u0000\u0000\u15fe\u15ff\u0005_\u0000\u0000"+ + "\u15ff\u1600\u0007\u0006\u0000\u0000\u1600\u1601\u0007\n\u0000\u0000\u1601"+ + "\u1602\u0007\u0007\u0000\u0000\u1602\u1603\u0007\u0017\u0000\u0000\u1603"+ + "\u1604\u0007\u0010\u0000\u0000\u1604\u1605\u0007\u0014\u0000\u0000\u1605"+ + "\u0488\u0001\u0000\u0000\u0000\u1606\u1607\u0007\u000e\u0000\u0000\u1607"+ + "\u1608\u0007\u0014\u0000\u0000\u1608\u1609\u0007\u0005\u0000\u0000\u1609"+ + "\u160a\u0007\r\u0000\u0000\u160a\u160b\u0005_\u0000\u0000\u160b\u160c"+ + "\u0007\u0006\u0000\u0000\u160c\u160d\u0007\n\u0000\u0000\u160d\u160e\u0007"+ + "\u0007\u0000\u0000\u160e\u160f\u0007\u0017\u0000\u0000\u160f\u1610\u0007"+ + "\u0010\u0000\u0000\u1610\u1611\u0007\u0014\u0000\u0000\u1611\u048a\u0001"+ + "\u0000\u0000\u0000\u1612\u1613\u0007\u000e\u0000\u0000\u1613\u1614\u0007"+ + "\u0014\u0000\u0000\u1614\u1615\u0007\u0005\u0000\u0000\u1615\u1616\u0007"+ + "\r\u0000\u0000\u1616\u1617\u0007\u0005\u0000\u0000\u1617\u1618\u0007\u000e"+ + "\u0000\u0000\u1618\u1619\u0007\u0010\u0000\u0000\u1619\u161a\u0007\n\u0000"+ + "\u0000\u161a\u161b\u0007\r\u0000\u0000\u161b\u161c\u0005_\u0000\u0000"+ + "\u161c\u161d\u0007\u0006\u0000\u0000\u161d\u161e\u0007\n\u0000\u0000\u161e"+ + "\u161f\u0007\u0007\u0000\u0000\u161f\u1620\u0007\u0017\u0000\u0000\u1620"+ + "\u1621\u0007\u0010\u0000\u0000\u1621\u1622\u0007\u0014\u0000\u0000\u1622"+ + "\u048c\u0001\u0000\u0000\u0000\u1623\u1624\u0007\u0006\u0000\u0000\u1624"+ + "\u1625\u0007\u0013\u0000\u0000\u1625\u1626\u0007\u001d\u0000\u0000\u1626"+ + "\u1627\u0007\n\u0000\u0000\u1627\u1628\u0007\r\u0000\u0000\u1628\u048e"+ + "\u0001\u0000\u0000\u0000\u1629\u162a\u0007\u0013\u0000\u0000\u162a\u162b"+ + "\u0007\u000e\u0000\u0000\u162b\u162c\u0007\u0010\u0000\u0000\u162c\u162d"+ + "\u0007\n\u0000\u0000\u162d\u162e\u0007\u0010\u0000\u0000\u162e\u162f\u0005"+ + "_\u0000\u0000\u162f\u1630\u0007\u0006\u0000\u0000\u1630\u1631\u0007\n"+ + "\u0000\u0000\u1631\u1632\u0007\u0007\u0000\u0000\u1632\u1633\u0007\u0017"+ + "\u0000\u0000\u1633\u1634\u0007\u0010\u0000\u0000\u1634\u1635\u0007\u0014"+ + "\u0000\u0000\u1635\u0490\u0001\u0000\u0000\u0000\u1636\u1637\u0007\u0016"+ + "\u0000\u0000\u1637\u1638\u0007\u0018\u0000\u0000\u1638\u1639\u0007\u0018"+ + "\u0000\u0000\u1639\u163a\u0007\n\u0000\u0000\u163a\u163b\u0007\r\u0000"+ + "\u0000\u163b\u0492\u0001\u0000\u0000\u0000\u163c\u163d\u0007\u0005\u0000"+ + "\u0000\u163d\u163e\u0007\t\u0000\u0000\u163e\u163f\u0007\u000e\u0000\u0000"+ + "\u163f\u1640\u0007\u0011\u0000\u0000\u1640\u1641\u0007\u0011\u0000\u0000"+ + "\u1641\u0494\u0001\u0000\u0000\u0000\u1642\u1643\u0007\u0012\u0000\u0000"+ + "\u1643\u1644\u0007\u0010\u0000\u0000\u1644\u1645\u0007\r\u0000\u0000\u1645"+ + "\u1646\u0007\u0011\u0000\u0000\u1646\u1647\u0007\u000f\u0000\u0000\u1647"+ + "\u0496\u0001\u0000\u0000\u0000\u1648\u1649\u0007\u000e\u0000\u0000\u1649"+ + "\u164a\u0007\u0014\u0000\u0000\u164a\u164b\u0007\r\u0000\u0000\u164b\u0498"+ + "\u0001\u0000\u0000\u0000\u164c\u164d\u0007\u000e\u0000\u0000\u164d\u164e"+ + "\u0007\u0013\u0000\u0000\u164e\u164f\u0007\u0007\u0000\u0000\u164f\u1650"+ + "\u0007\u000e\u0000\u0000\u1650\u1651\u0007\u0005\u0000\u0000\u1651\u1652"+ + "\u0007\u0010\u0000\u0000\u1652\u049a\u0001\u0000\u0000\u0000\u1653\u1654"+ + "\u0007\u000e\u0000\u0000\u1654\u1655\u0007\u0013\u0000\u0000\u1655\u1656"+ + "\u0007\u0007\u0000\u0000\u1656\u1657\u0007\u000e\u0000\u0000\u1657\u1658"+ + "\u0007\u0005\u0000\u0000\u1658\u1659\u0007\u0010\u0000\u0000\u1659\u165a"+ + "\u0005_\u0000\u0000\u165a\u165b\u0007\u001d\u0000\u0000\u165b\u165c\u0007"+ + "\t\u0000\u0000\u165c\u049c\u0001\u0000\u0000\u0000\u165d\u165e\u0007\u0019"+ + "\u0000\u0000\u165e\u165f\u0007\u0013\u0000\u0000\u165f\u1660\u0007\r\u0000"+ + "\u0000\u1660\u1661\u0007\u000f\u0000\u0000\u1661\u1662\u0007\u0005\u0000"+ + "\u0000\u1662\u1663\u0007\u0010\u0000\u0000\u1663\u049e\u0001\u0000\u0000"+ + "\u0000\u1664\u1665\u0007\u0011\u0000\u0000\u1665\u1666\u0007\u0007\u0000"+ + "\u0000\u1666\u1667\u0007\u0011\u0000\u0000\u1667\u1668\u0007\u0010\u0000"+ + "\u0000\u1668\u1669\u0007\u000e\u0000\u0000\u1669\u166a\u0007\u0005\u0000"+ + "\u0000\u166a\u166b\u0007\u0018\u0000\u0000\u166b\u04a0\u0001\u0000\u0000"+ + "\u0000\u166c\u166d\u0007\u0006\u0000\u0000\u166d\u166e\u0007\n\u0000\u0000"+ + "\u166e\u166f\u0007\u0007\u0000\u0000\u166f\u1670\u0007\u0017\u0000\u0000"+ + "\u1670\u1671\u0007\u0010\u0000\u0000\u1671\u1672\u0007\u0014\u0000\u0000"+ + "\u1672\u04a2\u0001\u0000\u0000\u0000\u1673\u1674\u0007\u0006\u0000\u0000"+ + "\u1674\u1675\u0007\u0018\u0000\u0000\u1675\u1676\u0007\u0005\u0000\u0000"+ + "\u1676\u1677\u0007\f\u0000\u0000\u1677\u04a4\u0001\u0000\u0000\u0000\u1678"+ + "\u1679\u0007\u0006\u0000\u0000\u1679\u167a\u0007\u0010\u0000\u0000\u167a"+ + "\u167b\u0007\r\u0000\u0000\u167b\u167c\u0007\u0011\u0000\u0000\u167c\u167d"+ + "\u0007\u000f\u0000\u0000\u167d\u04a6\u0001\u0000\u0000\u0000\u167e\u167f"+ + "\u0007\u000f\u0000\u0000\u167f\u1680\u0007\f\u0000\u0000\u1680\u1681\u0005"+ + "5\u0000\u0000\u1681\u04a8\u0001\u0000\u0000\u0000\u1682\u1683\u0007\u0018"+ + "\u0000\u0000\u1683\u1684\u0007\u0005\u0000\u0000\u1684\u1685\u0007\r\u0000"+ + "\u0000\u1685\u1686\u0007\t\u0000\u0000\u1686\u1687\u0007\n\u0000\u0000"+ + "\u1687\u1688\u0005_\u0000\u0000\u1688\u1689\u0007\u0011\u0000\u0000\u1689"+ + "\u168a\u0007\f\u0000\u0000\u168a\u168b\u0007\n\u0000\u0000\u168b\u168c"+ + "\u0007\u0007\u0000\u0000\u168c\u168d\u0007\u0010\u0000\u0000\u168d\u04aa"+ + "\u0001\u0000\u0000\u0000\u168e\u168f\u0007\u0018\u0000\u0000\u168f\u1690"+ + "\u0007\u0017\u0000\u0000\u1690\u1691\u0005_\u0000\u0000\u1691\u1692\u0007"+ + "\u000e\u0000\u0000\u1692\u1693\u0007\u0006\u0000\u0000\u1693\u1694\u0007"+ + "\u0011\u0000\u0000\u1694\u1695\u0007\n\u0000\u0000\u1695\u1696\u0007\u0007"+ + "\u0000\u0000\u1696\u1697\u0007\u0010\u0000\u0000\u1697\u1698\u0005_\u0000"+ + "\u0000\u1698\u1699\u0007\n\u0000\u0000\u1699\u169a\u0007\u0007\u0000\u0000"+ + "\u169a\u169b\u0007\u000e\u0000\u0000\u169b\u169c\u0007\u0013\u0000\u0000"+ + "\u169c\u169d\u0007\f\u0000\u0000\u169d\u169e\u0007\u0011\u0000\u0000\u169e"+ + "\u169f\u0007\u0007\u0000\u0000\u169f\u16a0\u0007\u0017\u0000\u0000\u16a0"+ + "\u04ac\u0001\u0000\u0000\u0000\u16a1\u16a2\u0007\u001c\u0000\u0000\u16a2"+ + "\u16a3\u0007\u0016\u0000\u0000\u16a3\u16a4\u0007\u0013\u0000\u0000\u16a4"+ + "\u16a5\u0007\u0010\u0000\u0000\u16a5\u16a6\u0007\n\u0000\u0000\u16a6\u16a7"+ + "\u0005_\u0000\u0000\u16a7\u16a8\u0007\u0011\u0000\u0000\u16a8\u16a9\u0007"+ + "\f\u0000\u0000\u16a9\u16aa\u0007\n\u0000\u0000\u16aa\u16ab\u0007\u0007"+ + "\u0000\u0000\u16ab\u16ac\u0007\u0010\u0000\u0000\u16ac\u04ae\u0001\u0000"+ + "\u0000\u0000\u16ad\u16ae\u0007\u001c\u0000\u0000\u16ae\u16af\u0007\u0016"+ + "\u0000\u0000\u16af\u16b0\u0007\u0013\u0000\u0000\u16b0\u16b1\u0007\u0010"+ + "\u0000\u0000\u16b1\u16b2\u0007\n\u0000\u0000\u16b2\u16b3\u0005_\u0000"+ + "\u0000\u16b3\u16b4\u0007\u0006\u0000\u0000\u16b4\u16b5\u0007\u0011\u0000"+ + "\u0000\u16b5\u16b6\u0007\u0010\u0000\u0000\u16b6\u16b7\u0007\n\u0000\u0000"+ + "\u16b7\u16b8\u0007\r\u0000\u0000\u16b8\u16b9\u0007\u0005\u0000\u0000\u16b9"+ + "\u16ba\u0007\u0006\u0000\u0000\u16ba\u04b0\u0001\u0000\u0000\u0000\u16bb"+ + "\u16bc\u0007\u001c\u0000\u0000\u16bc\u16bd\u0007\u0016\u0000\u0000\u16bd"+ + "\u16be\u0007\u0013\u0000\u0000\u16be\u16bf\u0007\u0010\u0000\u0000\u16bf"+ + "\u16c0\u0007\n\u0000\u0000\u16c0\u16c1\u0005_\u0000\u0000\u16c1\u16c2"+ + "\u0007\u0007\u0000\u0000\u16c2\u16c3\u0007\u0016\u0000\u0000\u16c3\u16c4"+ + "\u0007\u0006\u0000\u0000\u16c4\u16c5\u0007\u0006\u0000\u0000\u16c5\u16c6"+ + "\u0007\u0005\u0000\u0000\u16c6\u16c7\u0007\u0012\u0000\u0000\u16c7\u16c8"+ + "\u0007\u0006\u0000\u0000\u16c8\u16c9\u0007\n\u0000\u0000\u16c9\u04b2\u0001"+ + "\u0000\u0000\u0000\u16ca\u16cb\u0007\r\u0000\u0000\u16cb\u16cc\u0007\n"+ + "\u0000\u0000\u16cc\u16cd\u0007\u0017\u0000\u0000\u16cd\u16ce\u0007\n\u0000"+ + "\u0000\u16ce\u16cf\u0007\u001a\u0000\u0000\u16cf\u16d0\u0007\u0018\u0000"+ + "\u0000\u16d0\u16d1\u0005_\u0000\u0000\u16d1\u16d2\u0007\u000e\u0000\u0000"+ + "\u16d2\u16d3\u0007\u0013\u0000\u0000\u16d3\u16d4\u0007\u0016\u0000\u0000"+ + "\u16d4\u16d5\u0007\u0007\u0000\u0000\u16d5\u16d6\u0007\u0010\u0000\u0000"+ + "\u16d6\u04b4\u0001\u0000\u0000\u0000\u16d7\u16d8\u0007\r\u0000\u0000\u16d8"+ + "\u16d9\u0007\n\u0000\u0000\u16d9\u16da\u0007\u0017\u0000\u0000\u16da\u16db"+ + "\u0007\n\u0000\u0000\u16db\u16dc\u0007\u001a\u0000\u0000\u16dc\u16dd\u0007"+ + "\u0018\u0000\u0000\u16dd\u16de\u0005_\u0000\u0000\u16de\u16df\u0007\u0011"+ + "\u0000\u0000\u16df\u16e0\u0007\u0007\u0000\u0000\u16e0\u16e1\u0007\t\u0000"+ + "\u0000\u16e1\u16e2\u0007\u0010\u0000\u0000\u16e2\u16e3\u0007\r\u0000\u0000"+ + "\u16e3\u04b6\u0001\u0000\u0000\u0000\u16e4\u16e5\u0007\r\u0000\u0000\u16e5"+ + "\u16e6\u0007\n\u0000\u0000\u16e6\u16e7\u0007\u0017\u0000\u0000\u16e7\u16e8"+ + "\u0007\n\u0000\u0000\u16e8\u16e9\u0007\u001a\u0000\u0000\u16e9\u16ea\u0007"+ + "\u0018\u0000\u0000\u16ea\u16eb\u0005_\u0000\u0000\u16eb\u16ec\u0007\u0006"+ + "\u0000\u0000\u16ec\u16ed\u0007\u0011\u0000\u0000\u16ed\u16ee\u0007\u0015"+ + "\u0000\u0000\u16ee\u16ef\u0007\n\u0000\u0000\u16ef\u04b8\u0001\u0000\u0000"+ + "\u0000\u16f0\u16f1\u0007\r\u0000\u0000\u16f1\u16f2\u0007\n\u0000\u0000"+ + "\u16f2\u16f3\u0007\u0017\u0000\u0000\u16f3\u16f4\u0007\n\u0000\u0000\u16f4"+ + "\u16f5\u0007\u001a\u0000\u0000\u16f5\u16f6\u0007\u0018\u0000\u0000\u16f6"+ + "\u16f7\u0005_\u0000\u0000\u16f7\u16f8\u0007\u000f\u0000\u0000\u16f8\u16f9"+ + "\u0007\u0005\u0000\u0000\u16f9\u16fa\u0007\u0010\u0000\u0000\u16fa\u16fb"+ + "\u0007\u000e\u0000\u0000\u16fb\u16fc\u0007\u0014\u0000\u0000\u16fc\u04ba"+ + "\u0001\u0000\u0000\u0000\u16fd\u16fe\u0007\r\u0000\u0000\u16fe\u16ff\u0007"+ + "\n\u0000\u0000\u16ff\u1700\u0007\u0017\u0000\u0000\u1700\u1701\u0007\n"+ + "\u0000\u0000\u1701\u1702\u0007\u001a\u0000\u0000\u1702\u1703\u0007\u0018"+ + "\u0000\u0000\u1703\u1704\u0005_\u0000\u0000\u1704\u1705\u0007\u000f\u0000"+ + "\u0000\u1705\u1706\u0007\u0005\u0000\u0000\u1706\u1707\u0007\u0010\u0000"+ + "\u0000\u1707\u1708\u0007\u000e\u0000\u0000\u1708\u1709\u0007\u0014\u0000"+ + "\u0000\u1709\u170a\u0007\n\u0000\u0000\u170a\u170b\u0007\t\u0000\u0000"+ + "\u170b\u04bc\u0001\u0000\u0000\u0000\u170c\u170d\u0007\r\u0000\u0000\u170d"+ + "\u170e\u0007\n\u0000\u0000\u170e\u170f\u0007\u0017\u0000\u0000\u170f\u1710"+ + "\u0007\n\u0000\u0000\u1710\u1711\u0007\u001a\u0000\u0000\u1711\u1712\u0007"+ + "\u0018\u0000\u0000\u1712\u1713\u0005_\u0000\u0000\u1713\u1714\u0007\r"+ + "\u0000\u0000\u1714\u1715\u0007\n\u0000\u0000\u1715\u1716\u0007\u0018\u0000"+ + "\u0000\u1716\u1717\u0007\u0006\u0000\u0000\u1717\u1718\u0007\u0005\u0000"+ + "\u0000\u1718\u1719\u0007\u000e\u0000\u0000\u1719\u171a\u0007\n\u0000\u0000"+ + "\u171a\u04be\u0001\u0000\u0000\u0000\u171b\u171c\u0007\r\u0000\u0000\u171c"+ + "\u171d\u0007\n\u0000\u0000\u171d\u171e\u0007\u0017\u0000\u0000\u171e\u171f"+ + "\u0007\n\u0000\u0000\u171f\u1720\u0007\u001a\u0000\u0000\u1720\u1721\u0007"+ + "\u0018\u0000\u0000\u1721\u1722\u0005_\u0000\u0000\u1722\u1723\u0007\t"+ + "\u0000\u0000\u1723\u1724\u0007\u0018\u0000\u0000\u1724\u1725\u0007\u0006"+ + "\u0000\u0000\u1725\u1726\u0007\u0011\u0000\u0000\u1726\u1727\u0007\u0010"+ + "\u0000\u0000\u1727\u1728\u0005_\u0000\u0000\u1728\u1729\u0007\u0010\u0000"+ + "\u0000\u1729\u172a\u0007\u0013\u0000\u0000\u172a\u172b\u0005_\u0000\u0000"+ + "\u172b\u172c\u0007\u0005\u0000\u0000\u172c\u172d\u0007\r\u0000\u0000\u172d"+ + "\u172e\u0007\r\u0000\u0000\u172e\u172f\u0007\u0005\u0000\u0000\u172f\u1730"+ + "\u0007\b\u0000\u0000\u1730\u04c0\u0001\u0000\u0000\u0000\u1731\u1732\u0007"+ + "\r\u0000\u0000\u1732\u1733\u0007\n\u0000\u0000\u1733\u1734\u0007\u0017"+ + "\u0000\u0000\u1734\u1735\u0007\n\u0000\u0000\u1735\u1736\u0007\u001a\u0000"+ + "\u0000\u1736\u1737\u0007\u0018\u0000\u0000\u1737\u1738\u0005_\u0000\u0000"+ + "\u1738\u1739\u0007\t\u0000\u0000\u1739\u173a\u0007\u0018\u0000\u0000\u173a"+ + "\u173b\u0007\u0006\u0000\u0000\u173b\u173c\u0007\u0011\u0000\u0000\u173c"+ + "\u173d\u0007\u0010\u0000\u0000\u173d\u173e\u0005_\u0000\u0000\u173e\u173f"+ + "\u0007\u0010\u0000\u0000\u173f\u1740\u0007\u0013\u0000\u0000\u1740\u1741"+ + "\u0005_\u0000\u0000\u1741\u1742\u0007\u0010\u0000\u0000\u1742\u1743\u0007"+ + "\u0005\u0000\u0000\u1743\u1744\u0007\u0012\u0000\u0000\u1744\u1745\u0007"+ + "\u0006\u0000\u0000\u1745\u1746\u0007\n\u0000\u0000\u1746\u04c2\u0001\u0000"+ + "\u0000\u0000\u1747\u1748\u0007\r\u0000\u0000\u1748\u1749\u0007\n\u0000"+ + "\u0000\u1749\u174a\u0007\u0017\u0000\u0000\u174a\u174b\u0007\n\u0000\u0000"+ + "\u174b\u174c\u0007\u001a\u0000\u0000\u174c\u174d\u0007\u0018\u0000\u0000"+ + "\u174d\u174e\u0005_\u0000\u0000\u174e\u174f\u0007\t\u0000\u0000\u174f"+ + "\u1750\u0007\u0016\u0000\u0000\u1750\u1751\u0007\u0012\u0000\u0000\u1751"+ + "\u1752\u0007\t\u0000\u0000\u1752\u1753\u0007\u0010\u0000\u0000\u1753\u1754"+ + "\u0007\r\u0000\u0000\u1754\u04c4\u0001\u0000\u0000\u0000\u1755\u1756\u0007"+ + "\r\u0000\u0000\u1756\u1757\u0007\n\u0000\u0000\u1757\u1758\u0007\u0018"+ + "\u0000\u0000\u1758\u1759\u0007\n\u0000\u0000\u1759\u175a\u0007\u0005\u0000"+ + "\u0000\u175a\u175b\u0007\u0010\u0000\u0000\u175b\u04c6\u0001\u0000\u0000"+ + "\u0000\u175c\u175d\u0007\r\u0000\u0000\u175d\u175e\u0007\u0018\u0000\u0000"+ + "\u175e\u175f\u0007\u0005\u0000\u0000\u175f\u1760\u0007\f\u0000\u0000\u1760"+ + "\u04c8\u0001\u0000\u0000\u0000\u1761\u1762\u0007\r\u0000\u0000\u1762\u1763"+ + "\u0007\u0010\u0000\u0000\u1763\u1764\u0007\r\u0000\u0000\u1764\u1765\u0007"+ + "\u0011\u0000\u0000\u1765\u1766\u0007\u000f\u0000\u0000\u1766\u04ca\u0001"+ + "\u0000\u0000\u0000\u1767\u1768\u0007\t\u0000\u0000\u1768\u1769\u0007\u0018"+ + "\u0000\u0000\u1769\u176a\u0007\u0006\u0000\u0000\u176a\u176b\u0007\u0011"+ + "\u0000\u0000\u176b\u176c\u0007\u0010\u0000\u0000\u176c\u176d\u0005_\u0000"+ + "\u0000\u176d\u176e\u0007\u0018\u0000\u0000\u176e\u176f\u0007\u0005\u0000"+ + "\u0000\u176f\u1770\u0007\r\u0000\u0000\u1770\u1771\u0007\u0010\u0000\u0000"+ + "\u1771\u04cc\u0001\u0000\u0000\u0000\u1772\u1773\u0007\t\u0000\u0000\u1773"+ + "\u1774\u0007\u0010\u0000\u0000\u1774\u1775\u0007\u0005\u0000\u0000\u1775"+ + "\u1776\u0007\r\u0000\u0000\u1776\u1777\u0007\u0010\u0000\u0000\u1777\u1778"+ + "\u0007\t\u0000\u0000\u1778\u1779\u0005_\u0000\u0000\u1779\u177a\u0007"+ + "\u001d\u0000\u0000\u177a\u177b\u0007\u0011\u0000\u0000\u177b\u177c\u0007"+ + "\u0010\u0000\u0000\u177c\u177d\u0007\u0014\u0000\u0000\u177d\u04ce\u0001"+ + "\u0000\u0000\u0000\u177e\u177f\u0007\t\u0000\u0000\u177f\u1780\u0007\u0010"+ + "\u0000\u0000\u1780\u1781\u0007\r\u0000\u0000\u1781\u1782\u0007\u0011\u0000"+ + "\u0000\u1782\u1783\u0007\u0007\u0000\u0000\u1783\u1784\u0007\u0017\u0000"+ + "\u0000\u1784\u1785\u0005_\u0000\u0000\u1785\u1786\u0007\u0010\u0000\u0000"+ + "\u1786\u1787\u0007\u0013\u0000\u0000\u1787\u1788\u0005_\u0000\u0000\u1788"+ + "\u1789\u0007\u0005\u0000\u0000\u1789\u178a\u0007\r\u0000\u0000\u178a\u178b"+ + "\u0007\r\u0000\u0000\u178b\u178c\u0007\u0005\u0000\u0000\u178c\u178d\u0007"+ + "\b\u0000\u0000\u178d\u04d0\u0001\u0000\u0000\u0000\u178e\u178f\u0007\t"+ + "\u0000\u0000\u178f\u1790\u0007\u0010\u0000\u0000\u1790\u1791\u0007\r\u0000"+ + "\u0000\u1791\u1792\u0007\u0011\u0000\u0000\u1792\u1793\u0007\u0007\u0000"+ + "\u0000\u1793\u1794\u0007\u0017\u0000\u0000\u1794\u1795\u0005_\u0000\u0000"+ + "\u1795\u1796\u0007\u0010\u0000\u0000\u1796\u1797\u0007\u0013\u0000\u0000"+ + "\u1797\u1798\u0005_\u0000\u0000\u1798\u1799\u0007\u0010\u0000\u0000\u1799"+ + "\u179a\u0007\u0005\u0000\u0000\u179a\u179b\u0007\u0012\u0000\u0000\u179b"+ + "\u179c\u0007\u0006\u0000\u0000\u179c\u179d\u0007\n\u0000\u0000\u179d\u04d2"+ + "\u0001\u0000\u0000\u0000\u179e\u179f\u0007\t\u0000\u0000\u179f\u17a0\u0007"+ + "\u0010\u0000\u0000\u17a0\u17a1\u0007\r\u0000\u0000\u17a1\u17a2\u0007\u0018"+ + "\u0000\u0000\u17a2\u17a3\u0007\u0013\u0000\u0000\u17a3\u17a4\u0007\t\u0000"+ + "\u0000\u17a4\u04d4\u0001\u0000\u0000\u0000\u17a5\u17a6\u0007\t\u0000\u0000"+ + "\u17a6\u17a7\u0007\u0016\u0000\u0000\u17a7\u17a8\u0007\u0012\u0000\u0000"+ + "\u17a8\u17a9\u0007\t\u0000\u0000\u17a9\u17aa\u0007\u0010\u0000\u0000\u17aa"+ + "\u17ab\u0007\r\u0000\u0000\u17ab\u04d6\u0001\u0000\u0000\u0000\u17ac\u17ad"+ + "\u0007\u0010\u0000\u0000\u17ad\u17ae\u0007\u0013\u0000\u0000\u17ae\u17af"+ + "\u0005_\u0000\u0000\u17af\u17b0\u0007\u0005\u0000\u0000\u17b0\u17b1\u0007"+ + "\t\u0000\u0000\u17b1\u17b2\u0007\u000e\u0000\u0000\u17b2\u17b3\u0007\u0011"+ + "\u0000\u0000\u17b3\u17b4\u0007\u0011\u0000\u0000\u17b4\u04d8\u0001\u0000"+ + "\u0000\u0000\u17b5\u17b6\u0007\u0010\u0000\u0000\u17b6\u17b7\u0007\u0013"+ + "\u0000\u0000\u17b7\u17b8\u0005_\u0000\u0000\u17b8\u17b9\u0007\u0014\u0000"+ + "\u0000\u17b9\u17ba\u0007\n\u0000\u0000\u17ba\u17bb\u0007\u001a\u0000\u0000"+ + "\u17bb\u04da\u0001\u0000\u0000\u0000\u17bc\u17bd\u0007\u0010\u0000\u0000"+ + "\u17bd\u17be\u0007\r\u0000\u0000\u17be\u17bf\u0007\u0005\u0000\u0000\u17bf"+ + "\u17c0\u0007\u0007\u0000\u0000\u17c0\u17c1\u0007\t\u0000\u0000\u17c1\u17c2"+ + "\u0007\u0006\u0000\u0000\u17c2\u17c3\u0007\u0005\u0000\u0000\u17c3\u17c4"+ + "\u0007\u0010\u0000\u0000\u17c4\u17c5\u0007\n\u0000\u0000\u17c5\u04dc\u0001"+ + "\u0000\u0000\u0000\u17c6\u17c7\u0007\u0016\u0000\u0000\u17c7\u17c8\u0007"+ + "\u0007\u0000\u0000\u17c8\u17c9\u0007\u0011\u0000\u0000\u17c9\u17ca\u0007"+ + "\t\u0000\u0000\u17ca\u17cb\u0007\u0010\u0000\u0000\u17cb\u17cc\u0007\r"+ + "\u0000\u0000\u17cc\u04de\u0001\u0000\u0000\u0000\u17cd\u17ce\u0007\u0005"+ + "\u0000\u0000\u17ce\u17cf\u0007\u0017\u0000\u0000\u17cf\u17d0\u0007\n\u0000"+ + "\u0000\u17d0\u04e0\u0001\u0000\u0000\u0000\u17d1\u17d2\u0007\u000e\u0000"+ + "\u0000\u17d2\u17d3\u0007\u0006\u0000\u0000\u17d3\u17d4\u0007\u0013\u0000"+ + "\u0000\u17d4\u17d5\u0007\u000e\u0000\u0000\u17d5\u17d6\u0007\u0015\u0000"+ + "\u0000\u17d6\u17d7\u0005_\u0000\u0000\u17d7\u17d8\u0007\u0010\u0000\u0000"+ + "\u17d8\u17d9\u0007\u0011\u0000\u0000\u17d9\u17da\u0007\u000f\u0000\u0000"+ + "\u17da\u17db\u0007\n\u0000\u0000\u17db\u17dc\u0007\t\u0000\u0000\u17dc"+ + "\u17dd\u0007\u0010\u0000\u0000\u17dd\u17de\u0007\u0005\u0000\u0000\u17de"+ + "\u17df\u0007\u000f\u0000\u0000\u17df\u17e0\u0007\u0018\u0000\u0000\u17e0"+ + "\u04e2\u0001\u0000\u0000\u0000\u17e1\u17e2\u0007\f\u0000\u0000\u17e2\u17e3"+ + "\u0007\u0005\u0000\u0000\u17e3\u17e4\u0007\u0010\u0000\u0000\u17e4\u17e5"+ + "\u0007\n\u0000\u0000\u17e5\u17e6\u0005_\u0000\u0000\u17e6\u17e7\u0007"+ + "\u0012\u0000\u0000\u17e7\u17e8\u0007\u0011\u0000\u0000\u17e8\u17e9\u0007"+ + "\u0007\u0000\u0000\u17e9\u04e4\u0001\u0000\u0000\u0000\u17ea\u17eb\u0007"+ + "\f\u0000\u0000\u17eb\u17ec\u0007\u0005\u0000\u0000\u17ec\u17ed\u0007\u0010"+ + "\u0000\u0000\u17ed\u17ee\u0007\n\u0000\u0000\u17ee\u17ef\u0005_\u0000"+ + "\u0000\u17ef\u17f0\u0007\u0018\u0000\u0000\u17f0\u17f1\u0007\u0005\u0000"+ + "\u0000\u17f1\u17f2\u0007\r\u0000\u0000\u17f2\u17f3\u0007\u0010\u0000\u0000"+ + "\u17f3\u04e6\u0001\u0000\u0000\u0000\u17f4\u17f5\u0007\f\u0000\u0000\u17f5"+ + "\u17f6\u0007\u0005\u0000\u0000\u17f6\u17f7\u0007\u0010\u0000\u0000\u17f7"+ + "\u17f8\u0007\n\u0000\u0000\u17f8\u17f9\u0005_\u0000\u0000\u17f9\u17fa"+ + "\u0007\u0010\u0000\u0000\u17fa\u17fb\u0007\r\u0000\u0000\u17fb\u17fc\u0007"+ + "\u0016\u0000\u0000\u17fc\u17fd\u0007\u0007\u0000\u0000\u17fd\u17fe\u0007"+ + "\u000e\u0000\u0000\u17fe\u04e8\u0001\u0000\u0000\u0000\u17ff\u1800\u0007"+ + "\u0011\u0000\u0000\u1800\u1801\u0007\t\u0000\u0000\u1801\u1802\u0007\u0019"+ + "\u0000\u0000\u1802\u1803\u0007\u0011\u0000\u0000\u1803\u1804\u0007\u0007"+ + "\u0000\u0000\u1804\u1805\u0007\u0011\u0000\u0000\u1805\u1806\u0007\u0010"+ + "\u0000\u0000\u1806\u1807\u0007\n\u0000\u0000\u1807\u04ea\u0001\u0000\u0000"+ + "\u0000\u1808\u1809\u0007\u001e\u0000\u0000\u1809\u180a\u0007\u0016\u0000"+ + "\u0000\u180a\u180b\u0007\t\u0000\u0000\u180b\u180c\u0007\u0010\u0000\u0000"+ + "\u180c\u180d\u0007\u0011\u0000\u0000\u180d\u180e\u0007\u0019\u0000\u0000"+ + "\u180e\u180f\u0007\b\u0000\u0000\u180f\u1810\u0005_\u0000\u0000\u1810"+ + "\u1811\u0007\f\u0000\u0000\u1811\u1812\u0007\u0005\u0000\u0000\u1812\u1813"+ + "\u0007\b\u0000\u0000\u1813\u1814\u0007\t\u0000\u0000\u1814\u04ec\u0001"+ + "\u0000\u0000\u0000\u1815\u1816\u0007\u001e\u0000\u0000\u1816\u1817\u0007"+ + "\u0016\u0000\u0000\u1817\u1818\u0007\t\u0000\u0000\u1818\u1819\u0007\u0010"+ + "\u0000\u0000\u1819\u181a\u0007\u0011\u0000\u0000\u181a\u181b\u0007\u0019"+ + "\u0000\u0000\u181b\u181c\u0007\b\u0000\u0000\u181c\u181d\u0005_\u0000"+ + "\u0000\u181d\u181e\u0007\u0014\u0000\u0000\u181e\u181f\u0007\u0013\u0000"+ + "\u0000\u181f\u1820\u0007\u0016\u0000\u0000\u1820\u1821\u0007\r\u0000\u0000"+ + "\u1821\u1822\u0007\t\u0000\u0000\u1822\u04ee\u0001\u0000\u0000\u0000\u1823"+ + "\u1824\u0007\u001e\u0000\u0000\u1824\u1825\u0007\u0016\u0000\u0000\u1825"+ + "\u1826\u0007\t\u0000\u0000\u1826\u1827\u0007\u0010\u0000\u0000\u1827\u1828"+ + "\u0007\u0011\u0000\u0000\u1828\u1829\u0007\u0019\u0000\u0000\u1829\u182a"+ + "\u0007\b\u0000\u0000\u182a\u182b\u0005_\u0000\u0000\u182b\u182c\u0007"+ + "\u0011\u0000\u0000\u182c\u182d\u0007\u0007\u0000\u0000\u182d\u182e\u0007"+ + "\u0010\u0000\u0000\u182e\u182f\u0007\n\u0000\u0000\u182f\u1830\u0007\r"+ + "\u0000\u0000\u1830\u1831\u0007\u001b\u0000\u0000\u1831\u1832\u0007\u0005"+ + "\u0000\u0000\u1832\u1833\u0007\u0006\u0000\u0000\u1833\u04f0\u0001\u0000"+ + "\u0000\u0000\u1834\u1835\u0007\u000f\u0000\u0000\u1835\u1836\u0007\u0005"+ + "\u0000\u0000\u1836\u1837\u0007\u0015\u0000\u0000\u1837\u1838\u0007\n\u0000"+ + "\u0000\u1838\u1839\u0005_\u0000\u0000\u1839\u183a\u0007\f\u0000\u0000"+ + "\u183a\u183b\u0007\u0005\u0000\u0000\u183b\u183c\u0007\u0010\u0000\u0000"+ + "\u183c\u183d\u0007\n\u0000\u0000\u183d\u04f2\u0001\u0000\u0000\u0000\u183e"+ + "\u183f\u0007\u000f\u0000\u0000\u183f\u1840\u0007\u0005\u0000\u0000\u1840"+ + "\u1841\u0007\u0015\u0000\u0000\u1841\u1842\u0007\n\u0000\u0000\u1842\u1843"+ + "\u0005_\u0000\u0000\u1843\u1844\u0007\u0011\u0000\u0000\u1844\u1845\u0007"+ + "\u0007\u0000\u0000\u1845\u1846\u0007\u0010\u0000\u0000\u1846\u1847\u0007"+ + "\n\u0000\u0000\u1847\u1848\u0007\r\u0000\u0000\u1848\u1849\u0007\u001b"+ + "\u0000\u0000\u1849\u184a\u0007\u0005\u0000\u0000\u184a\u184b\u0007\u0006"+ + "\u0000\u0000\u184b\u04f4\u0001\u0000\u0000\u0000\u184c\u184d\u0007\u000f"+ + "\u0000\u0000\u184d\u184e\u0007\u0005\u0000\u0000\u184e\u184f\u0007\u0015"+ + "\u0000\u0000\u184f\u1850\u0007\n\u0000\u0000\u1850\u1851\u0005_\u0000"+ + "\u0000\u1851\u1852\u0007\u0010\u0000\u0000\u1852\u1853\u0007\u0011\u0000"+ + "\u0000\u1853\u1854\u0007\u000f\u0000\u0000\u1854\u1855\u0007\n\u0000\u0000"+ + "\u1855\u04f6\u0001\u0000\u0000\u0000\u1856\u1857\u0007\u000f\u0000\u0000"+ + "\u1857\u1858\u0007\u0005\u0000\u0000\u1858\u1859\u0007\u0015\u0000\u0000"+ + "\u1859\u185a\u0007\n\u0000\u0000\u185a\u185b\u0005_\u0000\u0000\u185b"+ + "\u185c\u0007\u0010\u0000\u0000\u185c\u185d\u0007\u0011\u0000\u0000\u185d"+ + "\u185e\u0007\u000f\u0000\u0000\u185e\u185f\u0007\n\u0000\u0000\u185f\u1860"+ + "\u0007\t\u0000\u0000\u1860\u1861\u0007\u0010\u0000\u0000\u1861\u1862\u0007"+ + "\u0005\u0000\u0000\u1862\u1863\u0007\u000f\u0000\u0000\u1863\u1864\u0007"+ + "\u0018\u0000\u0000\u1864\u04f8\u0001\u0000\u0000\u0000\u1865\u1866\u0007"+ + "\u000f\u0000\u0000\u1866\u1867\u0007\u0005\u0000\u0000\u1867\u1868\u0007"+ + "\u0015\u0000\u0000\u1868\u1869\u0007\n\u0000\u0000\u1869\u186a\u0005_"+ + "\u0000\u0000\u186a\u186b\u0007\u0010\u0000\u0000\u186b\u186c\u0007\u0011"+ + "\u0000\u0000\u186c\u186d\u0007\u000f\u0000\u0000\u186d\u186e\u0007\n\u0000"+ + "\u0000\u186e\u186f\u0007\t\u0000\u0000\u186f\u1870\u0007\u0010\u0000\u0000"+ + "\u1870\u1871\u0007\u0005\u0000\u0000\u1871\u1872\u0007\u000f\u0000\u0000"+ + "\u1872\u1873\u0007\u0018\u0000\u0000\u1873\u1874\u0007\u0010\u0000\u0000"+ + "\u1874\u1875\u0007\u000b\u0000\u0000\u1875\u04fa\u0001\u0000\u0000\u0000"+ + "\u1876\u1877\u0007\u0007\u0000\u0000\u1877\u1878\u0007\u0013\u0000\u0000"+ + "\u1878\u1879\u0007\u001d\u0000\u0000\u1879\u04fc\u0001\u0000\u0000\u0000"+ + "\u187a\u187b\u0007\t\u0000\u0000\u187b\u187c\u0007\u0010\u0000\u0000\u187c"+ + "\u187d\u0007\u0005\u0000\u0000\u187d\u187e\u0007\u0010\u0000\u0000\u187e"+ + "\u187f\u0007\n\u0000\u0000\u187f\u1880\u0007\u000f\u0000\u0000\u1880\u1881"+ + "\u0007\n\u0000\u0000\u1881\u1882\u0007\u0007\u0000\u0000\u1882\u1883\u0007"+ + "\u0010\u0000\u0000\u1883\u1884\u0005_\u0000\u0000\u1884\u1885\u0007\u0010"+ + "\u0000\u0000\u1885\u1886\u0007\u0011\u0000\u0000\u1886\u1887\u0007\u000f"+ + "\u0000\u0000\u1887\u1888\u0007\n\u0000\u0000\u1888\u1889\u0007\t\u0000"+ + "\u0000\u1889\u188a\u0007\u0010\u0000\u0000\u188a\u188b\u0007\u0005\u0000"+ + "\u0000\u188b\u188c\u0007\u000f\u0000\u0000\u188c\u188d\u0007\u0018\u0000"+ + "\u0000\u188d\u04fe\u0001\u0000\u0000\u0000\u188e\u188f\u0007\u0010\u0000"+ + "\u0000\u188f\u1890\u0007\u0011\u0000\u0000\u1890\u1891\u0007\u000f\u0000"+ + "\u0000\u1891\u1892\u0007\n\u0000\u0000\u1892\u1893\u0007\u0013\u0000\u0000"+ + "\u1893\u1894\u0007\u0019\u0000\u0000\u1894\u1895\u0007\f\u0000\u0000\u1895"+ + "\u1896\u0007\u0005\u0000\u0000\u1896\u1897\u0007\b\u0000\u0000\u1897\u0500"+ + "\u0001\u0000\u0000\u0000\u1898\u1899\u0007\u0010\u0000\u0000\u1899\u189a"+ + "\u0007\r\u0000\u0000\u189a\u189b\u0007\u0005\u0000\u0000\u189b\u189c\u0007"+ + "\u0007\u0000\u0000\u189c\u189d\u0007\t\u0000\u0000\u189d\u189e\u0007\u0005"+ + "\u0000\u0000\u189e\u189f\u0007\u000e\u0000\u0000\u189f\u18a0\u0007\u0010"+ + "\u0000\u0000\u18a0\u18a1\u0007\u0011\u0000\u0000\u18a1\u18a2\u0007\u0013"+ + "\u0000\u0000\u18a2\u18a3\u0007\u0007\u0000\u0000\u18a3\u18a4\u0005_\u0000"+ + "\u0000\u18a4\u18a5\u0007\u0010\u0000\u0000\u18a5\u18a6\u0007\u0011\u0000"+ + "\u0000\u18a6\u18a7\u0007\u000f\u0000\u0000\u18a7\u18a8\u0007\n\u0000\u0000"+ + "\u18a8\u18a9\u0007\t\u0000\u0000\u18a9\u18aa\u0007\u0010\u0000\u0000\u18aa"+ + "\u18ab\u0007\u0005\u0000\u0000\u18ab\u18ac\u0007\u000f\u0000\u0000\u18ac"+ + "\u18ad\u0007\u0018\u0000\u0000\u18ad\u0502\u0001\u0000\u0000\u0000\u18ae"+ + "\u18af\u0007\u0010\u0000\u0000\u18af\u18b0\u0007\u0013\u0000\u0000\u18b0"+ + "\u18b1\u0005_\u0000\u0000\u18b1\u18b2\u0007\u0010\u0000\u0000\u18b2\u18b3"+ + "\u0007\u0011\u0000\u0000\u18b3\u18b4\u0007\u000f\u0000\u0000\u18b4\u18b5"+ + "\u0007\n\u0000\u0000\u18b5\u18b6\u0007\t\u0000\u0000\u18b6\u18b7\u0007"+ + "\u0010\u0000\u0000\u18b7\u18b8\u0007\u0005\u0000\u0000\u18b8\u18b9\u0007"+ + "\u000f\u0000\u0000\u18b9\u18ba\u0007\u0018\u0000\u0000\u18ba\u0504\u0001"+ + "\u0000\u0000\u0000\u18bb\u18bc\u0007\u0010\u0000\u0000\u18bc\u18bd\u0007"+ + "\u0013\u0000\u0000\u18bd\u18be\u0005_\u0000\u0000\u18be\u18bf\u0007\u000e"+ + "\u0000\u0000\u18bf\u18c0\u0007\u0014\u0000\u0000\u18c0\u18c1\u0007\u0005"+ + "\u0000\u0000\u18c1\u18c2\u0007\r\u0000\u0000\u18c2\u0506\u0001\u0000\u0000"+ + "\u0000\u18c3\u18c4\u0007\u0010\u0000\u0000\u18c4\u18c5\u0007\u0013\u0000"+ + "\u0000\u18c5\u18c6\u0005_\u0000\u0000\u18c6\u18c7\u0007\f\u0000\u0000"+ + "\u18c7\u18c8\u0007\u0005\u0000\u0000\u18c8\u18c9\u0007\u0010\u0000\u0000"+ + "\u18c9\u18ca\u0007\n\u0000\u0000\u18ca\u0508\u0001\u0000\u0000\u0000\u18cb"+ + "\u18cc\u0007\u0010\u0000\u0000\u18cc\u18cd\u0007\u0013\u0000\u0000\u18cd"+ + "\u18ce\u0005_\u0000\u0000\u18ce\u18cf\u0007\u0007\u0000\u0000\u18cf\u18d0"+ + "\u0007\u0016\u0000\u0000\u18d0\u18d1\u0007\u000f\u0000\u0000\u18d1\u18d2"+ + "\u0007\u0012\u0000\u0000\u18d2\u18d3\u0007\n\u0000\u0000\u18d3\u18d4\u0007"+ + "\r\u0000\u0000\u18d4\u050a\u0001\u0000\u0000\u0000\u18d5\u18d9\u0003\u050d"+ + "\u0284\u0000\u18d6\u18d8\u0003\u050f\u0285\u0000\u18d7\u18d6\u0001\u0000"+ + "\u0000\u0000\u18d8\u18db\u0001\u0000\u0000\u0000\u18d9\u18d7\u0001\u0000"+ + "\u0000\u0000\u18d9\u18da\u0001\u0000\u0000\u0000\u18da\u050c\u0001\u0000"+ + "\u0000\u0000\u18db\u18d9\u0001\u0000\u0000\u0000\u18dc\u18e3\u0007\u001f"+ + "\u0000\u0000\u18dd\u18de\u0007 \u0000\u0000\u18de\u18e3\u0004\u0284\u0006"+ + "\u0000\u18df\u18e0\u0007!\u0000\u0000\u18e0\u18e1\u0007\"\u0000\u0000"+ + "\u18e1\u18e3\u0004\u0284\u0007\u0000\u18e2\u18dc\u0001\u0000\u0000\u0000"+ + "\u18e2\u18dd\u0001\u0000\u0000\u0000\u18e2\u18df\u0001\u0000\u0000\u0000"+ + "\u18e3\u050e\u0001\u0000\u0000\u0000\u18e4\u18e7\u0003\u0511\u0286\u0000"+ + "\u18e5\u18e7\u0005$\u0000\u0000\u18e6\u18e4\u0001\u0000\u0000\u0000\u18e6"+ + "\u18e5\u0001\u0000\u0000\u0000\u18e7\u0510\u0001\u0000\u0000\u0000\u18e8"+ + "\u18eb\u0003\u050d\u0284\u0000\u18e9\u18eb\u0007\u0000\u0000\u0000\u18ea"+ + "\u18e8\u0001\u0000\u0000\u0000\u18ea\u18e9\u0001\u0000\u0000\u0000\u18eb"+ + "\u0512\u0001\u0000\u0000\u0000\u18ec\u18ed\u0003\u0515\u0288\u0000\u18ed"+ + "\u18ee\u0005\"\u0000\u0000\u18ee\u0514\u0001\u0000\u0000\u0000\u18ef\u18f5"+ + "\u0005\"\u0000\u0000\u18f0\u18f1\u0005\"\u0000\u0000\u18f1\u18f4\u0005"+ + "\"\u0000\u0000\u18f2\u18f4\b#\u0000\u0000\u18f3\u18f0\u0001\u0000\u0000"+ + "\u0000\u18f3\u18f2\u0001\u0000\u0000\u0000\u18f4\u18f7\u0001\u0000\u0000"+ + "\u0000\u18f5\u18f3\u0001\u0000\u0000\u0000\u18f5\u18f6\u0001\u0000\u0000"+ + "\u0000\u18f6\u0516\u0001\u0000\u0000\u0000\u18f7\u18f5\u0001\u0000\u0000"+ + "\u0000\u18f8\u18f9\u0003\u0519\u028a\u0000\u18f9\u18fa\u0005\"\u0000\u0000"+ + "\u18fa\u0518\u0001\u0000\u0000\u0000\u18fb\u1901\u0005\"\u0000\u0000\u18fc"+ + "\u18fd\u0005\"\u0000\u0000\u18fd\u1900\u0005\"\u0000\u0000\u18fe\u1900"+ + "\b$\u0000\u0000\u18ff\u18fc\u0001\u0000\u0000\u0000\u18ff\u18fe\u0001"+ + "\u0000\u0000\u0000\u1900\u1903\u0001\u0000\u0000\u0000\u1901\u18ff\u0001"+ + "\u0000\u0000\u0000\u1901\u1902\u0001\u0000\u0000\u0000\u1902\u051a\u0001"+ + "\u0000\u0000\u0000\u1903\u1901\u0001\u0000\u0000\u0000\u1904\u1905\u0007"+ + "\u0016\u0000\u0000\u1905\u1906\u0005&\u0000\u0000\u1906\u1907\u0003\u0513"+ + "\u0287\u0000\u1907\u051c\u0001\u0000\u0000\u0000\u1908\u1909\u0007\u0016"+ + "\u0000\u0000\u1909\u190a\u0005&\u0000\u0000\u190a\u190b\u0003\u0515\u0288"+ + "\u0000\u190b\u051e\u0001\u0000\u0000\u0000\u190c\u190d\u0007\u0016\u0000"+ + "\u0000\u190d\u190e\u0005&\u0000\u0000\u190e\u190f\u0003\u0517\u0289\u0000"+ + "\u190f\u0520\u0001\u0000\u0000\u0000\u1910\u1911\u0007\u0016\u0000\u0000"+ + "\u1911\u1912\u0005&\u0000\u0000\u1912\u1913\u0003\u0519\u028a\u0000\u1913"+ + "\u0522\u0001\u0000\u0000\u0000\u1914\u1915\u0003\u0525\u0290\u0000\u1915"+ + "\u1916\u0005\'\u0000\u0000\u1916\u0524\u0001\u0000\u0000\u0000\u1917\u191f"+ + "\u0005\'\u0000\u0000\u1918\u1919\u0005\'\u0000\u0000\u1919\u191e\u0005"+ + "\'\u0000\u0000\u191a\u191e\b%\u0000\u0000\u191b\u191c\u0005\\\u0000\u0000"+ + "\u191c\u191e\u0005\'\u0000\u0000\u191d\u1918\u0001\u0000\u0000\u0000\u191d"+ + "\u191a\u0001\u0000\u0000\u0000\u191d\u191b\u0001\u0000\u0000\u0000\u191e"+ + "\u1921\u0001\u0000\u0000\u0000\u191f\u191d\u0001\u0000\u0000\u0000\u191f"+ + "\u1920\u0001\u0000\u0000\u0000\u1920\u0526\u0001\u0000\u0000\u0000\u1921"+ + "\u191f\u0001\u0000\u0000\u0000\u1922\u1923\u0007\n\u0000\u0000\u1923\u1924"+ + "\u0005\'\u0000\u0000\u1924\u1925\u0001\u0000\u0000\u0000\u1925\u1926\u0006"+ + "\u0291\u0002\u0000\u1926\u1927\u0006\u0291\u0003\u0000\u1927\u0528\u0001"+ + "\u0000\u0000\u0000\u1928\u1929\u0003\u052b\u0293\u0000\u1929\u192a\u0005"+ + "\'\u0000\u0000\u192a\u052a\u0001\u0000\u0000\u0000\u192b\u192c\u0007\u0016"+ + "\u0000\u0000\u192c\u192d\u0005&\u0000\u0000\u192d\u192e\u0003\u0525\u0290"+ + "\u0000\u192e\u052c\u0001\u0000\u0000\u0000\u192f\u1931\u0005$\u0000\u0000"+ + "\u1930\u1932\u0003\u052f\u0295\u0000\u1931\u1930\u0001\u0000\u0000\u0000"+ + "\u1931\u1932\u0001\u0000\u0000\u0000\u1932\u1933\u0001\u0000\u0000\u0000"+ + "\u1933\u1934\u0005$\u0000\u0000\u1934\u1935\u0006\u0294\u0004\u0000\u1935"+ + "\u1936\u0001\u0000\u0000\u0000\u1936\u1937\u0006\u0294\u0005\u0000\u1937"+ + "\u052e\u0001\u0000\u0000\u0000\u1938\u193c\u0003\u050d\u0284\u0000\u1939"+ + "\u193b\u0003\u0511\u0286\u0000\u193a\u1939\u0001\u0000\u0000\u0000\u193b"+ + "\u193e\u0001\u0000\u0000\u0000\u193c\u193a\u0001\u0000\u0000\u0000\u193c"+ + "\u193d\u0001\u0000\u0000\u0000\u193d\u0530\u0001\u0000\u0000\u0000\u193e"+ + "\u193c\u0001\u0000\u0000\u0000\u193f\u1940\u0003\u0533\u0297\u0000\u1940"+ + "\u1941\u0005\'\u0000\u0000\u1941\u0532\u0001\u0000\u0000\u0000\u1942\u1943"+ + "\u0007\u0012\u0000\u0000\u1943\u1947\u0005\'\u0000\u0000\u1944\u1946\u0007"+ + "&\u0000\u0000\u1945\u1944\u0001\u0000\u0000\u0000\u1946\u1949\u0001\u0000"+ + "\u0000\u0000\u1947\u1945\u0001\u0000\u0000\u0000\u1947\u1948\u0001\u0000"+ + "\u0000\u0000\u1948\u0534\u0001\u0000\u0000\u0000\u1949\u1947\u0001\u0000"+ + "\u0000\u0000\u194a\u194b\u0003\u0537\u0299\u0000\u194b\u194c\u0005\'\u0000"+ + "\u0000\u194c\u0536\u0001\u0000\u0000\u0000\u194d\u194e\u0007\u0012\u0000"+ + "\u0000\u194e\u194f\u0003\u0525\u0290\u0000\u194f\u0538\u0001\u0000\u0000"+ + "\u0000\u1950\u1951\u0003\u053b\u029b\u0000\u1951\u1952\u0005\'\u0000\u0000"+ + "\u1952\u053a\u0001\u0000\u0000\u0000\u1953\u1954\u0007\u001a\u0000\u0000"+ + "\u1954\u1958\u0005\'\u0000\u0000\u1955\u1957\u0007\'\u0000\u0000\u1956"+ + "\u1955\u0001\u0000\u0000\u0000\u1957\u195a\u0001\u0000\u0000\u0000\u1958"+ + "\u1956\u0001\u0000\u0000\u0000\u1958\u1959\u0001\u0000\u0000\u0000\u1959"+ + "\u053c\u0001\u0000\u0000\u0000\u195a\u1958\u0001\u0000\u0000\u0000\u195b"+ + "\u195c\u0003\u053f\u029d\u0000\u195c\u195d\u0005\'\u0000\u0000\u195d\u053e"+ + "\u0001\u0000\u0000\u0000\u195e\u195f\u0007\u001a\u0000\u0000\u195f\u1960"+ + "\u0003\u0525\u0290\u0000\u1960\u0540\u0001\u0000\u0000\u0000\u1961\u1962"+ + "\u0003\u0547\u02a1\u0000\u1962\u0542\u0001\u0000\u0000\u0000\u1963\u1964"+ + "\u0003\u0547\u02a1\u0000\u1964\u1965\u0005.\u0000\u0000\u1965\u1966\u0005"+ + ".\u0000\u0000\u1966\u1967\u0001\u0000\u0000\u0000\u1967\u1968\u0006\u029f"+ + "\u0006\u0000\u1968\u0544\u0001\u0000\u0000\u0000\u1969\u196a\u0003\u0547"+ + "\u02a1\u0000\u196a\u196c\u0005.\u0000\u0000\u196b\u196d\u0003\u0547\u02a1"+ + "\u0000\u196c\u196b\u0001\u0000\u0000\u0000\u196c\u196d\u0001\u0000\u0000"+ + "\u0000\u196d\u1973\u0001\u0000\u0000\u0000\u196e\u1970\u0007\n\u0000\u0000"+ + "\u196f\u1971\u0007\u0001\u0000\u0000\u1970\u196f\u0001\u0000\u0000\u0000"+ + "\u1970\u1971\u0001\u0000\u0000\u0000\u1971\u1972\u0001\u0000\u0000\u0000"+ + "\u1972\u1974\u0003\u0547\u02a1\u0000\u1973\u196e\u0001\u0000\u0000\u0000"+ + "\u1973\u1974\u0001\u0000\u0000\u0000\u1974\u1986\u0001\u0000\u0000\u0000"+ + "\u1975\u1976\u0005.\u0000\u0000\u1976\u197c\u0003\u0547\u02a1\u0000\u1977"+ + "\u1979\u0007\n\u0000\u0000\u1978\u197a\u0007\u0001\u0000\u0000\u1979\u1978"+ + "\u0001\u0000\u0000\u0000\u1979\u197a\u0001\u0000\u0000\u0000\u197a\u197b"+ + "\u0001\u0000\u0000\u0000\u197b\u197d\u0003\u0547\u02a1\u0000\u197c\u1977"+ + "\u0001\u0000\u0000\u0000\u197c\u197d\u0001\u0000\u0000\u0000\u197d\u1986"+ + "\u0001\u0000\u0000\u0000\u197e\u197f\u0003\u0547\u02a1\u0000\u197f\u1981"+ + "\u0007\n\u0000\u0000\u1980\u1982\u0007\u0001\u0000\u0000\u1981\u1980\u0001"+ + "\u0000\u0000\u0000\u1981\u1982\u0001\u0000\u0000\u0000\u1982\u1983\u0001"+ + "\u0000\u0000\u0000\u1983\u1984\u0003\u0547\u02a1\u0000\u1984\u1986\u0001"+ + "\u0000\u0000\u0000\u1985\u1969\u0001\u0000\u0000\u0000\u1985\u1975\u0001"+ + "\u0000\u0000\u0000\u1985\u197e\u0001\u0000\u0000\u0000\u1986\u0546\u0001"+ + "\u0000\u0000\u0000\u1987\u1989\u0007\u0000\u0000\u0000\u1988\u1987\u0001"+ + "\u0000\u0000\u0000\u1989\u198a\u0001\u0000\u0000\u0000\u198a\u1988\u0001"+ + "\u0000\u0000\u0000\u198a\u198b\u0001\u0000\u0000\u0000\u198b\u0548\u0001"+ + "\u0000\u0000\u0000\u198c\u198d\u0005:\u0000\u0000\u198d\u198e\u0005\""+ + "\u0000\u0000\u198e\u1996\u0001\u0000\u0000\u0000\u198f\u1990\u0005\\\u0000"+ + "\u0000\u1990\u1995\t\u0000\u0000\u0000\u1991\u1992\u0005\"\u0000\u0000"+ + "\u1992\u1995\u0005\"\u0000\u0000\u1993\u1995\b(\u0000\u0000\u1994\u198f"+ + "\u0001\u0000\u0000\u0000\u1994\u1991\u0001\u0000\u0000\u0000\u1994\u1993"+ + "\u0001\u0000\u0000\u0000\u1995\u1998\u0001\u0000\u0000\u0000\u1996\u1994"+ + "\u0001\u0000\u0000\u0000\u1996\u1997\u0001\u0000\u0000\u0000\u1997\u1999"+ + "\u0001\u0000\u0000\u0000\u1998\u1996\u0001\u0000\u0000\u0000\u1999\u199a"+ + "\u0005\"\u0000\u0000\u199a\u054a\u0001\u0000\u0000\u0000\u199b\u199d\u0007"+ + ")\u0000\u0000\u199c\u199b\u0001\u0000\u0000\u0000\u199d\u199e\u0001\u0000"+ + "\u0000\u0000\u199e\u199c\u0001\u0000\u0000\u0000\u199e\u199f\u0001\u0000"+ + "\u0000\u0000\u199f\u19a0\u0001\u0000\u0000\u0000\u19a0\u19a1\u0006\u02a3"+ + "\u0007\u0000\u19a1\u054c\u0001\u0000\u0000\u0000\u19a2\u19a4\u0005\r\u0000"+ + "\u0000\u19a3\u19a5\u0005\n\u0000\u0000\u19a4\u19a3\u0001\u0000\u0000\u0000"+ + "\u19a4\u19a5\u0001\u0000\u0000\u0000\u19a5\u19a8\u0001\u0000\u0000\u0000"+ + "\u19a6\u19a8\u0005\n\u0000\u0000\u19a7\u19a2\u0001\u0000\u0000\u0000\u19a7"+ + "\u19a6\u0001\u0000\u0000\u0000\u19a8\u19a9\u0001\u0000\u0000\u0000\u19a9"+ + "\u19aa\u0006\u02a4\u0007\u0000\u19aa\u054e\u0001\u0000\u0000\u0000\u19ab"+ + "\u19ac\u0005-\u0000\u0000\u19ac\u19ad\u0005-\u0000\u0000\u19ad\u19b1\u0001"+ + "\u0000\u0000\u0000\u19ae\u19b0\b*\u0000\u0000\u19af\u19ae\u0001\u0000"+ + "\u0000\u0000\u19b0\u19b3\u0001\u0000\u0000\u0000\u19b1\u19af\u0001\u0000"+ + "\u0000\u0000\u19b1\u19b2\u0001\u0000\u0000\u0000\u19b2\u19b4\u0001\u0000"+ + "\u0000\u0000\u19b3\u19b1\u0001\u0000\u0000\u0000\u19b4\u19b5\u0006\u02a5"+ + "\u0007\u0000\u19b5\u0550\u0001\u0000\u0000\u0000\u19b6\u19b7\u0005/\u0000"+ + "\u0000\u19b7\u19b8\u0005*\u0000\u0000\u19b8\u19cf\u0001\u0000\u0000\u0000"+ + "\u19b9\u19bb\u0005/\u0000\u0000\u19ba\u19b9\u0001\u0000\u0000\u0000\u19bb"+ + "\u19be\u0001\u0000\u0000\u0000\u19bc\u19ba\u0001\u0000\u0000\u0000\u19bc"+ + "\u19bd\u0001\u0000\u0000\u0000\u19bd\u19bf\u0001\u0000\u0000\u0000\u19be"+ + "\u19bc\u0001\u0000\u0000\u0000\u19bf\u19ce\u0003\u0551\u02a6\u0000\u19c0"+ + "\u19ce\b+\u0000\u0000\u19c1\u19c3\u0005/\u0000\u0000\u19c2\u19c1\u0001"+ + "\u0000\u0000\u0000\u19c3\u19c4\u0001\u0000\u0000\u0000\u19c4\u19c2\u0001"+ + "\u0000\u0000\u0000\u19c4\u19c5\u0001\u0000\u0000\u0000\u19c5\u19c6\u0001"+ + "\u0000\u0000\u0000\u19c6\u19ce\b+\u0000\u0000\u19c7\u19c9\u0005*\u0000"+ + "\u0000\u19c8\u19c7\u0001\u0000\u0000\u0000\u19c9\u19ca\u0001\u0000\u0000"+ + "\u0000\u19ca\u19c8\u0001\u0000\u0000\u0000\u19ca\u19cb\u0001\u0000\u0000"+ + "\u0000\u19cb\u19cc\u0001\u0000\u0000\u0000\u19cc\u19ce\b+\u0000\u0000"+ + "\u19cd\u19bc\u0001\u0000\u0000\u0000\u19cd\u19c0\u0001\u0000\u0000\u0000"+ + "\u19cd\u19c2\u0001\u0000\u0000\u0000\u19cd\u19c8\u0001\u0000\u0000\u0000"+ + "\u19ce\u19d1\u0001\u0000\u0000\u0000\u19cf\u19cd\u0001\u0000\u0000\u0000"+ + "\u19cf\u19d0\u0001\u0000\u0000\u0000\u19d0\u19d5\u0001\u0000\u0000\u0000"+ + "\u19d1\u19cf\u0001\u0000\u0000\u0000\u19d2\u19d4\u0005*\u0000\u0000\u19d3"+ + "\u19d2\u0001\u0000\u0000\u0000\u19d4\u19d7\u0001\u0000\u0000\u0000\u19d5"+ + "\u19d3\u0001\u0000\u0000\u0000\u19d5\u19d6\u0001\u0000\u0000\u0000\u19d6"+ + "\u19d8\u0001\u0000\u0000\u0000\u19d7\u19d5\u0001\u0000\u0000\u0000\u19d8"+ + "\u19d9\u0005*\u0000\u0000\u19d9\u19da\u0005/\u0000\u0000\u19da\u19db\u0001"+ + "\u0000\u0000\u0000\u19db\u19dc\u0006\u02a6\u0007\u0000\u19dc\u0552\u0001"+ + "\u0000\u0000\u0000\u19dd\u19de\u0005/\u0000\u0000\u19de\u19df\u0005*\u0000"+ + "\u0000\u19df\u19f8\u0001\u0000\u0000\u0000\u19e0\u19e2\u0005/\u0000\u0000"+ + "\u19e1\u19e0\u0001\u0000\u0000\u0000\u19e2\u19e5\u0001\u0000\u0000\u0000"+ + "\u19e3\u19e1\u0001\u0000\u0000\u0000\u19e3\u19e4\u0001\u0000\u0000\u0000"+ + "\u19e4\u19e6\u0001\u0000\u0000\u0000\u19e5\u19e3\u0001\u0000\u0000\u0000"+ + "\u19e6\u19f7\u0003\u0551\u02a6\u0000\u19e7\u19f7\b+\u0000\u0000\u19e8"+ + "\u19ea\u0005/\u0000\u0000\u19e9\u19e8\u0001\u0000\u0000\u0000\u19ea\u19eb"+ + "\u0001\u0000\u0000\u0000\u19eb\u19e9\u0001\u0000\u0000\u0000\u19eb\u19ec"+ + "\u0001\u0000\u0000\u0000\u19ec\u19ed\u0001\u0000\u0000\u0000\u19ed\u19f5"+ + "\b+\u0000\u0000\u19ee\u19f0\u0005*\u0000\u0000\u19ef\u19ee\u0001\u0000"+ + "\u0000\u0000\u19f0\u19f1\u0001\u0000\u0000\u0000\u19f1\u19ef\u0001\u0000"+ + "\u0000\u0000\u19f1\u19f2\u0001\u0000\u0000\u0000\u19f2\u19f3\u0001\u0000"+ + "\u0000\u0000\u19f3\u19f5\b+\u0000\u0000\u19f4\u19e9\u0001\u0000\u0000"+ + "\u0000\u19f4\u19ef\u0001\u0000\u0000\u0000\u19f5\u19f7\u0001\u0000\u0000"+ + "\u0000\u19f6\u19e3\u0001\u0000\u0000\u0000\u19f6\u19e7\u0001\u0000\u0000"+ + "\u0000\u19f6\u19f4\u0001\u0000\u0000\u0000\u19f7\u19fa\u0001\u0000\u0000"+ + "\u0000\u19f8\u19f6\u0001\u0000\u0000\u0000\u19f8\u19f9\u0001\u0000\u0000"+ + "\u0000\u19f9\u1a0c\u0001\u0000\u0000\u0000\u19fa\u19f8\u0001\u0000\u0000"+ + "\u0000\u19fb\u19fd\u0005/\u0000\u0000\u19fc\u19fb\u0001\u0000\u0000\u0000"+ + "\u19fd\u19fe\u0001\u0000\u0000\u0000\u19fe\u19fc\u0001\u0000\u0000\u0000"+ + "\u19fe\u19ff\u0001\u0000\u0000\u0000\u19ff\u1a0d\u0001\u0000\u0000\u0000"+ + "\u1a00\u1a02\u0005*\u0000\u0000\u1a01\u1a00\u0001\u0000\u0000\u0000\u1a02"+ + "\u1a03\u0001\u0000\u0000\u0000\u1a03\u1a01\u0001\u0000\u0000\u0000\u1a03"+ + "\u1a04\u0001\u0000\u0000\u0000\u1a04\u1a0d\u0001\u0000\u0000\u0000\u1a05"+ + "\u1a07\u0005/\u0000\u0000\u1a06\u1a05\u0001\u0000\u0000\u0000\u1a07\u1a0a"+ + "\u0001\u0000\u0000\u0000\u1a08\u1a06\u0001\u0000\u0000\u0000\u1a08\u1a09"+ + "\u0001\u0000\u0000\u0000\u1a09\u1a0b\u0001\u0000\u0000\u0000\u1a0a\u1a08"+ + "\u0001\u0000\u0000\u0000\u1a0b\u1a0d\u0003\u0553\u02a7\u0000\u1a0c\u19fc"+ + "\u0001\u0000\u0000\u0000\u1a0c\u1a01\u0001\u0000\u0000\u0000\u1a0c\u1a08"+ + "\u0001\u0000\u0000\u0000\u1a0c\u1a0d\u0001\u0000\u0000\u0000\u1a0d\u1a0e"+ + "\u0001\u0000\u0000\u0000\u1a0e\u1a0f\u0006\u02a7\b\u0000\u1a0f\u0554\u0001"+ + "\u0000\u0000\u0000\u1a10\u1a1c\u0005\\\u0000\u0000\u1a11\u1a1b\b,\u0000"+ + "\u0000\u1a12\u1a16\u0005\"\u0000\u0000\u1a13\u1a15\b-\u0000\u0000\u1a14"+ + "\u1a13\u0001\u0000\u0000\u0000\u1a15\u1a18\u0001\u0000\u0000\u0000\u1a16"+ + "\u1a14\u0001\u0000\u0000\u0000\u1a16\u1a17\u0001\u0000\u0000\u0000\u1a17"+ + "\u1a19\u0001\u0000\u0000\u0000\u1a18\u1a16\u0001\u0000\u0000\u0000\u1a19"+ + "\u1a1b\u0005\"\u0000\u0000\u1a1a\u1a11\u0001\u0000\u0000\u0000\u1a1a\u1a12"+ + "\u0001\u0000\u0000\u0000\u1a1b\u1a1e\u0001\u0000\u0000\u0000\u1a1c\u1a1a"+ + "\u0001\u0000\u0000\u0000\u1a1c\u1a1d\u0001\u0000\u0000\u0000\u1a1d\u1a26"+ + "\u0001\u0000\u0000\u0000\u1a1e\u1a1c\u0001\u0000\u0000\u0000\u1a1f\u1a23"+ + "\u0005\"\u0000\u0000\u1a20\u1a22\b-\u0000\u0000\u1a21\u1a20\u0001\u0000"+ + "\u0000\u0000\u1a22\u1a25\u0001\u0000\u0000\u0000\u1a23\u1a21\u0001\u0000"+ + "\u0000\u0000\u1a23\u1a24\u0001\u0000\u0000\u0000\u1a24\u1a27\u0001\u0000"+ + "\u0000\u0000\u1a25\u1a23\u0001\u0000\u0000\u0000\u1a26\u1a1f\u0001\u0000"+ + "\u0000\u0000\u1a26\u1a27\u0001\u0000\u0000\u0000\u1a27\u0556\u0001\u0000"+ + "\u0000\u0000\u1a28\u1a29\u0005\\\u0000\u0000\u1a29\u1a2a\u0005\\\u0000"+ + "\u0000\u1a2a\u0558\u0001\u0000\u0000\u0000\u1a2b\u1a2c\t\u0000\u0000\u0000"+ + "\u1a2c\u055a\u0001\u0000\u0000\u0000\u1a2d\u1a2e\u0003\u055f\u02ad\u0000"+ + "\u1a2e\u1a2f\u0005\'\u0000\u0000\u1a2f\u1a30\u0001\u0000\u0000\u0000\u1a30"+ + "\u1a31\u0006\u02ab\t\u0000\u1a31\u055c\u0001\u0000\u0000\u0000\u1a32\u1a34"+ + "\u0003\u055f\u02ad\u0000\u1a33\u1a35\u0005\\\u0000\u0000\u1a34\u1a33\u0001"+ + "\u0000\u0000\u0000\u1a34\u1a35\u0001\u0000\u0000\u0000\u1a35\u1a36\u0001"+ + "\u0000\u0000\u0000\u1a36\u1a37\u0005\u0000\u0000\u0001\u1a37\u055e\u0001"+ + "\u0000\u0000\u0000\u1a38\u1a39\u0005\\\u0000\u0000\u1a39\u1a50\u0005\'"+ + "\u0000\u0000\u1a3a\u1a4c\u0005\\\u0000\u0000\u1a3b\u1a3c\u0005x\u0000"+ + "\u0000\u1a3c\u1a4d\u0007\'\u0000\u0000\u1a3d\u1a3e\u0005u\u0000\u0000"+ + "\u1a3e\u1a3f\u0007\'\u0000\u0000\u1a3f\u1a40\u0007\'\u0000\u0000\u1a40"+ + "\u1a41\u0007\'\u0000\u0000\u1a41\u1a4d\u0007\'\u0000\u0000\u1a42\u1a43"+ + "\u0005U\u0000\u0000\u1a43\u1a44\u0007\'\u0000\u0000\u1a44\u1a45\u0007"+ + "\'\u0000\u0000\u1a45\u1a46\u0007\'\u0000\u0000\u1a46\u1a47\u0007\'\u0000"+ + "\u0000\u1a47\u1a48\u0007\'\u0000\u0000\u1a48\u1a49\u0007\'\u0000\u0000"+ + "\u1a49\u1a4a\u0007\'\u0000\u0000\u1a4a\u1a4d\u0007\'\u0000\u0000\u1a4b"+ + "\u1a4d\b.\u0000\u0000\u1a4c\u1a3b\u0001\u0000\u0000\u0000\u1a4c\u1a3d"+ + "\u0001\u0000\u0000\u0000\u1a4c\u1a42\u0001\u0000\u0000\u0000\u1a4c\u1a4b"+ + "\u0001\u0000\u0000\u0000\u1a4d\u1a50\u0001\u0000\u0000\u0000\u1a4e\u1a50"+ + "\b/\u0000\u0000\u1a4f\u1a38\u0001\u0000\u0000\u0000\u1a4f\u1a3a\u0001"+ + "\u0000\u0000\u0000\u1a4f\u1a4e\u0001\u0000\u0000\u0000\u1a50\u1a53\u0001"+ + "\u0000\u0000\u0000\u1a51\u1a4f\u0001\u0000\u0000\u0000\u1a51\u1a52\u0001"+ + "\u0000\u0000\u0000\u1a52\u0560\u0001\u0000\u0000\u0000\u1a53\u1a51\u0001"+ + "\u0000\u0000\u0000\u1a54\u1a55\u0003\u0565\u02b0\u0000\u1a55\u1a56\u0005"+ + "\'\u0000\u0000\u1a56\u1a57\u0001\u0000\u0000\u0000\u1a57\u1a58\u0006\u02ae"+ + "\t\u0000\u1a58\u0562\u0001\u0000\u0000\u0000\u1a59\u1a5b\u0003\u0565\u02b0"+ + "\u0000\u1a5a\u1a5c\u0005\\\u0000\u0000\u1a5b\u1a5a\u0001\u0000\u0000\u0000"+ + "\u1a5b\u1a5c\u0001\u0000\u0000\u0000\u1a5c\u1a5d\u0001\u0000\u0000\u0000"+ + "\u1a5d\u1a5e\u0005\u0000\u0000\u0001\u1a5e\u0564\u0001\u0000\u0000\u0000"+ + "\u1a5f\u1a60\u0005\'\u0000\u0000\u1a60\u1a65\u0005\'\u0000\u0000\u1a61"+ + "\u1a62\u0005\\\u0000\u0000\u1a62\u1a65\t\u0000\u0000\u0000\u1a63\u1a65"+ + "\b/\u0000\u0000\u1a64\u1a5f\u0001\u0000\u0000\u0000\u1a64\u1a61\u0001"+ + "\u0000\u0000\u0000\u1a64\u1a63\u0001\u0000\u0000\u0000\u1a65\u1a68\u0001"+ + "\u0000\u0000\u0000\u1a66\u1a64\u0001\u0000\u0000\u0000\u1a66\u1a67\u0001"+ + "\u0000\u0000\u0000\u1a67\u0566\u0001\u0000\u0000\u0000\u1a68\u1a66\u0001"+ + "\u0000\u0000\u0000\u1a69\u1a6a\u0003\u054b\u02a3\u0000\u1a6a\u1a6b\u0001"+ + "\u0000\u0000\u0000\u1a6b\u1a6c\u0006\u02b1\n\u0000\u1a6c\u1a6d\u0006\u02b1"+ + "\u0007\u0000\u1a6d\u0568\u0001\u0000\u0000\u0000\u1a6e\u1a6f\u0003\u054d"+ + "\u02a4\u0000\u1a6f\u1a70\u0001\u0000\u0000\u0000\u1a70\u1a71\u0006\u02b2"+ + "\u000b\u0000\u1a71\u1a72\u0006\u02b2\u0007\u0000\u1a72\u1a73\u0006\u02b2"+ + "\f\u0000\u1a73\u056a\u0001\u0000\u0000\u0000\u1a74\u1a75\u0003\u054b\u02a3"+ + "\u0000\u1a75\u1a76\u0001\u0000\u0000\u0000\u1a76\u1a77\u0006\u02b3\n\u0000"+ + "\u1a77\u1a78\u0006\u02b3\u0007\u0000\u1a78\u056c\u0001\u0000\u0000\u0000"+ + "\u1a79\u1a7a\u0003\u054d\u02a4\u0000\u1a7a\u1a7b\u0001\u0000\u0000\u0000"+ + "\u1a7b\u1a7c\u0006\u02b4\u000b\u0000\u1a7c\u1a7d\u0006\u02b4\u0007\u0000"+ + "\u1a7d\u056e\u0001\u0000\u0000\u0000\u1a7e\u1a7f\u0005\'\u0000\u0000\u1a7f"+ + "\u1a80\u0001\u0000\u0000\u0000\u1a80\u1a81\u0006\u02b5\u0002\u0000\u1a81"+ + "\u1a82\u0006\u02b5\r\u0000\u1a82\u0570\u0001\u0000\u0000\u0000\u1a83\u1a85"+ + "\b0\u0000\u0000\u1a84\u1a83\u0001\u0000\u0000\u0000\u1a85\u1a86\u0001"+ + "\u0000\u0000\u0000\u1a86\u1a84\u0001\u0000\u0000\u0000\u1a86\u1a87\u0001"+ + "\u0000\u0000\u0000\u1a87\u1a90\u0001\u0000\u0000\u0000\u1a88\u1a8c\u0005"+ + "$\u0000\u0000\u1a89\u1a8b\b0\u0000\u0000\u1a8a\u1a89\u0001\u0000\u0000"+ + "\u0000\u1a8b\u1a8e\u0001\u0000\u0000\u0000\u1a8c\u1a8a\u0001\u0000\u0000"+ + "\u0000\u1a8c\u1a8d\u0001\u0000\u0000\u0000\u1a8d\u1a90\u0001\u0000\u0000"+ + "\u0000\u1a8e\u1a8c\u0001\u0000\u0000\u0000\u1a8f\u1a84\u0001\u0000\u0000"+ + "\u0000\u1a8f\u1a88\u0001\u0000\u0000\u0000\u1a90\u0572\u0001\u0000\u0000"+ + "\u0000\u1a91\u1a93\u0005$\u0000\u0000\u1a92\u1a94\u0003\u052f\u0295\u0000"+ + "\u1a93\u1a92\u0001\u0000\u0000\u0000\u1a93\u1a94\u0001\u0000\u0000\u0000"+ + "\u1a94\u1a95\u0001\u0000\u0000\u0000\u1a95\u1a96\u0005$\u0000\u0000\u1a96"+ + "\u1a97\u0001\u0000\u0000\u0000\u1a97\u1a98\u0004\u02b7\b\u0000\u1a98\u1a99"+ + "\u0006\u02b7\u000e\u0000\u1a99\u1a9a\u0001\u0000\u0000\u0000\u1a9a\u1a9b"+ + "\u0006\u02b7\u000f\u0000\u1a9b\u0574\u0001\u0000\u0000\u0000O\u0000\u0001"+ + "\u0002\u0003\u0004\u057e\u05c6\u05cc\u05ce\u05d3\u05d7\u05d9\u05eb\u05ed"+ + "\u05f6\u05f8\u05fd\u0602\u0604\u18d9\u18e2\u18e6\u18ea\u18f3\u18f5\u18ff"+ + "\u1901\u191d\u191f\u1931\u193c\u1947\u1958\u196c\u1970\u1973\u1979\u197c"+ + "\u1981\u1985\u198a\u1994\u1996\u199e\u19a4\u19a7\u19b1\u19bc\u19c4\u19ca"+ + "\u19cd\u19cf\u19d5\u19e3\u19eb\u19f1\u19f4\u19f6\u19f8\u19fe\u1a03\u1a08"+ + "\u1a0c\u1a16\u1a1a\u1a1c\u1a23\u1a26\u1a34\u1a4c\u1a4f\u1a51\u1a5b\u1a64"+ + "\u1a66\u1a86\u1a8c\u1a8f\u1a93\u0010\u0001\u001f\u0000\u0007\u001f\u0000"+ + "\u0003\u0000\u0000\u0005\u0001\u0000\u0001\u0294\u0001\u0005\u0004\u0000"+ + "\u0001\u029f\u0002\u0000\u0001\u0000\u0001\u02a7\u0003\u0002\u0002\u0000"+ + "\u0007\u0299\u0000\u0007\u029a\u0000\u0002\u0003\u0000\u0002\u0001\u0000"+ + "\u0001\u02b7\u0004\u0004\u0000\u0000"; public static final String _serializedATN = Utils.join( new String[] { _serializedATNSegment0, diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/SpringDataConfig.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/SpringDataConfig.java index bb4343e8c..cde26d674 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/SpringDataConfig.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/SpringDataConfig.java @@ -14,11 +14,11 @@ import java.util.Optional; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.ide.vscode.boot.java.data.jpa.queries.AntlrReconcilerWithSpel; import org.springframework.ide.vscode.boot.java.data.jpa.queries.HqlSemanticTokens; import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlSemanticTokens; import org.springframework.ide.vscode.boot.java.data.jpa.queries.JpqlSupportState; import org.springframework.ide.vscode.boot.java.data.jpa.queries.QueryProblemType; +import org.springframework.ide.vscode.boot.java.embadded.lang.AntlrReconcilerWithSpel; import org.springframework.ide.vscode.boot.java.spel.SpelReconciler; import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens; import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/CronReconciler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/CronReconciler.java index 8d074fe33..646fe4d9b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/CronReconciler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/CronReconciler.java @@ -14,6 +14,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.BitSet; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; import org.antlr.v4.runtime.ANTLRErrorListener; import org.antlr.v4.runtime.CharStreams; @@ -35,6 +36,8 @@ import org.springframework.ide.vscode.boot.java.handlers.Reconciler; import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector; import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl; import org.springframework.ide.vscode.commons.util.BadLocationException; +import org.springframework.ide.vscode.commons.util.text.IRegion; +import org.springframework.ide.vscode.commons.util.text.Region; import org.springframework.ide.vscode.commons.util.text.linetracker.DefaultLineTracker; import org.springframework.ide.vscode.parser.cron.CronLexer; import org.springframework.ide.vscode.parser.cron.CronParser; @@ -62,7 +65,7 @@ public class CronReconciler implements Reconciler { } @Override - public void reconcile(String text, int startPosition, IProblemCollector problemCollector) { + public void reconcile(String text, Function mapping, IProblemCollector problemCollector) { CronLexer lexer = new CronLexer(CharStreams.fromString(text)); CommonTokenStream antlrTokens = new CommonTokenStream(lexer); CronParser parser = new CronParser(antlrTokens); @@ -117,7 +120,8 @@ public class CronReconciler implements Reconciler { if (message.startsWith("For input string:")) { markProblemsForNumberFormatException(ctx, message); } else { - problemCollector.accept(new ReconcileProblemImpl(CronProblemType.FIELD, "CRON: %s".formatted(message), startPosition + ctx.getStart().getStartIndex(), ctx.getText().length())); + IRegion r = mapping.apply(new Region(ctx.getStart().getStartIndex(), ctx.getText().length())); + problemCollector.accept(new ReconcileProblemImpl(CronProblemType.FIELD, "CRON: %s".formatted(message), r.getOffset(), r.getLength())); } } } @@ -132,12 +136,14 @@ public class CronReconciler implements Reconciler { String problemText = message.substring(start + 1, end); int offset = text.indexOf(problemText); if (offset >= 0) { - problemCollector.accept(new ReconcileProblemImpl(CronProblemType.FIELD, "CRON: Number expected", startPosition + ctx.getStart().getStartIndex() + offset, problemText.length())); + IRegion r = mapping.apply(new Region(ctx.getStart().getStartIndex() + offset, problemText.length())); + problemCollector.accept(new ReconcileProblemImpl(CronProblemType.FIELD, "CRON: Number expected", r.getOffset(), r.getLength())); return; } } } - problemCollector.accept(new ReconcileProblemImpl(CronProblemType.FIELD, "CRON: %s".formatted(message), startPosition + ctx.getStart().getStartIndex(), ctx.getText().length())); + IRegion r = mapping.apply(new Region(ctx.getStart().getStartIndex(), ctx.getText().length())); + problemCollector.accept(new ReconcileProblemImpl(CronProblemType.FIELD, "CRON: %s".formatted(message), r.getOffset(), r.getLength())); } @@ -169,7 +175,8 @@ public class CronReconciler implements Reconciler { log.error("", e1); } } - problemCollector.accept(new ReconcileProblemImpl(CronProblemType.SYNTAX, "CRON: " + msg, startPosition + offset, length)); + IRegion r = mapping.apply(new Region(offset, length)); + problemCollector.accept(new ReconcileProblemImpl(CronProblemType.SYNTAX, "CRON: " + msg, r.getOffset(), r.getLength())); } @Override diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/CronSemanticTokens.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/CronSemanticTokens.java index 8a3706ad6..75e956d89 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/CronSemanticTokens.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/CronSemanticTokens.java @@ -58,7 +58,7 @@ public class CronSemanticTokens implements SemanticTokensDataProvider { } @Override - public List computeTokens(String text, int initialOffset) { + public List computeTokens(String text) { CronLexer lexer = new CronLexer(CharStreams.fromString(text)); CommonTokenStream antlrTokens = new CommonTokenStream(lexer); CronParser parser = new CronParser(antlrTokens); @@ -157,8 +157,8 @@ public class CronSemanticTokens implements SemanticTokensDataProvider { parser.cronExpression(); tokens.addAll(semantics.entrySet().stream() - .map(e -> new SemanticTokenData(e.getKey().getStartIndex() + initialOffset, - e.getKey().getStartIndex() + e.getKey().getText().length() + initialOffset, e.getValue(), + .map(e -> new SemanticTokenData(e.getKey().getStartIndex(), + e.getKey().getStartIndex() + e.getKey().getText().length(), e.getValue(), new String[0])) .collect(Collectors.toList())); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronReconciler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronReconciler.java index 951db75f5..6a35206ad 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronReconciler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronReconciler.java @@ -15,7 +15,7 @@ import java.net.URI; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.NormalAnnotation; -import org.springframework.ide.vscode.boot.java.data.jpa.queries.JdtQueryVisitorUtils.EmbeddedExpression; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLanguageSnippet; import org.springframework.ide.vscode.boot.java.reconcilers.JdtAstReconciler; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.SpringProjectUtil; @@ -46,9 +46,9 @@ public class JdtCronReconciler implements JdtAstReconciler { return new ASTVisitor() { @Override public boolean visit(NormalAnnotation node) { - EmbeddedExpression e = JdtCronVisitorUtils.extractCron(node); + EmbeddedLanguageSnippet e = JdtCronVisitorUtils.extractCron(node); if (e != null) { - cronReconciler.reconcile(e.text(), e.offset(), problemCollector); + cronReconciler.reconcile(e.getText(), e::toSingleJavaRange, problemCollector); } return super.visit(node); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronSemanticTokensProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronSemanticTokensProvider.java index 0921bd4a8..b34966b2b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronSemanticTokensProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronSemanticTokensProvider.java @@ -16,7 +16,7 @@ import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.NormalAnnotation; import org.springframework.ide.vscode.boot.java.JdtSemanticTokensProvider; -import org.springframework.ide.vscode.boot.java.data.jpa.queries.JdtQueryVisitorUtils.EmbeddedExpression; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLanguageSnippet; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.SpringProjectUtil; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData; @@ -56,9 +56,12 @@ public class JdtCronSemanticTokensProvider implements JdtSemanticTokensProvider @Override public boolean visit(NormalAnnotation node) { - EmbeddedExpression e = JdtCronVisitorUtils.extractCron(node); + EmbeddedLanguageSnippet e = JdtCronVisitorUtils.extractCron(node); if (e != null) { - tokensProvider.computeTokens(e.text(), e.offset()).forEach(collector::accept); + tokensProvider.computeTokens(e.getText()).stream() + .flatMap(td -> e.toJavaRanges(td.range()).stream().map(r -> new SemanticTokenData(r, + td.type(), td.modifiers()))) + .forEach(collector::accept); } return super.visit(node); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronVisitorUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronVisitorUtils.java index 2d11ca90f..9c17ad4cf 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronVisitorUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/cron/JdtCronVisitorUtils.java @@ -10,8 +10,6 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.cron; -import static org.springframework.ide.vscode.boot.java.data.jpa.queries.JdtQueryVisitorUtils.extractEmbeddedExpression; - import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MemberValuePair; @@ -19,13 +17,14 @@ import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.StringLiteral; import org.eclipse.jdt.core.dom.TextBlock; import org.springframework.ide.vscode.boot.java.Annotations; -import org.springframework.ide.vscode.boot.java.data.jpa.queries.JdtQueryVisitorUtils.EmbeddedExpression; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLangAstUtils; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLanguageSnippet; public class JdtCronVisitorUtils { static final String SCHEDULED_SIMPLE_NAME = "Scheduled"; - public static EmbeddedExpression extractCron(NormalAnnotation node) { + public static EmbeddedLanguageSnippet extractCron(NormalAnnotation node) { if (node.getTypeName() != null) { String fqn = node.getTypeName().getFullyQualifiedName(); if (SCHEDULED_SIMPLE_NAME.equals(fqn) || Annotations.SCHEDULED.equals(fqn)) { @@ -36,7 +35,7 @@ public class JdtCronVisitorUtils { MemberValuePair pair = (MemberValuePair) value; String name = pair.getName().getFullyQualifiedName(); if (name != null && "cron".equals(name) && isCronExpression(pair.getValue())) { - return extractEmbeddedExpression(pair.getValue()); + return EmbeddedLangAstUtils.extractEmbeddedExpression(pair.getValue()); } } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/DataQueryParameterDefinitionProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/DataQueryParameterDefinitionProvider.java index c0f9d0500..eb6c97f0b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/DataQueryParameterDefinitionProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/DataQueryParameterDefinitionProvider.java @@ -57,14 +57,14 @@ public class DataQueryParameterDefinitionProvider implements IJavaDefinitionProv Collector collector = new Collector<>(); a.accept(semanticTokensProvider.getTokensComputer(project, doc, cu, collector)); for (SemanticTokenData t : collector.get()) { - if ("parameter".equals(t.type()) && t.start() <= offset && offset <= t.end()) { + if ("parameter".equals(t.type()) && t.range().getOffset() <= offset && offset <= t.range().getEnd()) { try { - String parameterDescriptor = doc.get(t.start(), t.end() - t.start()); + String parameterDescriptor = doc.get(t.range().getOffset(), t.range().getLength()); SimpleName paramName = JdtQueryDocHighlightsProvider.findParameter(m, parameterDescriptor); if (paramName != null) { LocationLink link = new LocationLink(); link.setTargetUri(docId.getUri()); - link.setOriginSelectionRange(doc.toRange(t.start(), t.end() - t.start())); + link.setOriginSelectionRange(doc.toRange(t.range().getOffset(), t.range().getLength())); link.setTargetSelectionRange(doc.toRange(paramName.getStartPosition(), paramName.getLength())); link.setTargetRange(link.getTargetSelectionRange()); return List.of(link); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/HqlSemanticTokens.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/HqlSemanticTokens.java index b847b1a5f..87be02e01 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/HqlSemanticTokens.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/HqlSemanticTokens.java @@ -32,6 +32,7 @@ import org.antlr.v4.runtime.atn.ATNConfigSet; import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.tree.ErrorNode; import org.antlr.v4.runtime.tree.TerminalNode; +import org.springframework.ide.vscode.boot.java.embadded.lang.AntlrUtils; import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensDataProvider; @@ -75,7 +76,7 @@ public class HqlSemanticTokens implements SemanticTokensDataProvider { } @Override - public List computeTokens(String text, int initialOffset) { + public List computeTokens(String text) { HqlLexer lexer = new HqlLexer(CharStreams.fromString(text)); CommonTokenStream antlrTokens = new CommonTokenStream(lexer); HqlParser parser = new HqlParser(antlrTokens); @@ -109,7 +110,7 @@ public class HqlSemanticTokens implements SemanticTokensDataProvider { case HqlParser.WS: break; case HqlParser.SPEL: - tokens.addAll(JpqlSemanticTokens.computeTokensFromSpelNode(node, initialOffset, optSpelTokens)); + tokens.addAll(JpqlSemanticTokens.computeTokensFromSpelNode(node, 0, optSpelTokens)); break; default: if (HqlParser.WS < type && type <= HqlParser.YEAR) { @@ -132,7 +133,7 @@ public class HqlSemanticTokens implements SemanticTokensDataProvider { @Override public void exitInstantiationTarget(InstantiationTargetContext ctx) { - int offset = initialOffset + ctx.getStart().getStartIndex(); + int offset = ctx.getStart().getStartIndex(); int length = ctx.getText().length(); tokens.add(new SemanticTokenData(offset, offset + length , "method", new String[0])); AntlrUtils.getAllLeafs(ctx).forEach(semantics::remove); @@ -189,8 +190,8 @@ public class HqlSemanticTokens implements SemanticTokensDataProvider { parser.ql_statement(); semantics.entrySet().stream() - .map(e -> new SemanticTokenData(e.getKey().getStartIndex() + initialOffset, - e.getKey().getStartIndex() + e.getKey().getText().length() + initialOffset, e.getValue(), + .map(e -> new SemanticTokenData(e.getKey().getStartIndex(), + e.getKey().getStartIndex() + e.getKey().getText().length(), e.getValue(), new String[0])) .forEach(tokens::add); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQueriesInlayHintsProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQueriesInlayHintsProvider.java index 960684b4d..21d81b7f6 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQueriesInlayHintsProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQueriesInlayHintsProvider.java @@ -75,12 +75,12 @@ public class JdtDataQueriesInlayHintsProvider implements JdtInlayHintsProvider { } private void processQuery(IJavaProject project, TextDocument doc, Collector collector, MethodDeclaration m, EmbeddedQueryExpression q) { - List semanticTokens = semanticTokensProvider.computeSemanticTokens(project, q.query().text(), q.query().offset(), q.isNative()); + List semanticTokens = semanticTokensProvider.computeSemanticTokens(project, q.query(), q.isNative()); SemanticTokenData previousToken = null; for (SemanticTokenData t : semanticTokens) { if (isValidParameterOrdinalInputParameterToken(doc, t, previousToken)) { try { - int number = Integer.parseInt(doc.get(t.start(), t.end() - t.start())); + int number = Integer.parseInt(doc.get(t.range().getOffset(), t.range().getLength())); if (number > 0 && number <= m.parameters().size()) { Object param = m.parameters().get(number - 1); if (param instanceof SingleVariableDeclaration svd) { @@ -90,7 +90,7 @@ public class JdtDataQueriesInlayHintsProvider implements JdtInlayHintsProvider { hint.setLabel(Either.forLeft(paramName)); hint.setPaddingLeft(true); hint.setPaddingRight(true); - hint.setPosition(doc.toPosition(firstNonSkippedChar(doc, t.end(), c -> '%' != c))); + hint.setPosition(doc.toPosition(firstNonSkippedChar(doc, t.range().getEnd(), c -> '%' != c))); collector.accept(hint); } @@ -111,7 +111,7 @@ public class JdtDataQueriesInlayHintsProvider implements JdtInlayHintsProvider { private static boolean isValidParameterOrdinalInputParameterToken(TextDocument doc, SemanticTokenData token, SemanticTokenData previous) { if ("parameter".equals(token.type()) && previous != null && "operator".equals(previous.type())) { try { - return "?".equals(doc.get(previous.start(), previous.end() - previous.start())); + return "?".equals(doc.get(previous.range().getOffset(), previous.range().getLength())); } catch (BadLocationException e) { // ignore } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQuerySemanticTokensProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQuerySemanticTokensProvider.java index bac9c8d76..20d53d6e7 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQuerySemanticTokensProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQuerySemanticTokensProvider.java @@ -25,6 +25,7 @@ import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.SingleMemberAnnotation; import org.springframework.ide.vscode.boot.java.JdtSemanticTokensProvider; import org.springframework.ide.vscode.boot.java.data.jpa.queries.JdtQueryVisitorUtils.EmbeddedQueryExpression; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLanguageSnippet; import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.SpringProjectUtil; @@ -68,7 +69,7 @@ public class JdtDataQuerySemanticTokensProvider implements JdtSemanticTokensProv public boolean visit(NormalAnnotation a) { EmbeddedQueryExpression q = JdtQueryVisitorUtils.extractQueryExpression(a); if (q != null) { - computeSemanticTokens(jp, q.query().text(), q.query().offset(), q.isNative()).forEach(tokensData::accept); + computeSemanticTokens(jp, q.query(), q.isNative()).forEach(tokensData::accept); } return super.visit(a); } @@ -77,7 +78,7 @@ public class JdtDataQuerySemanticTokensProvider implements JdtSemanticTokensProv public boolean visit(SingleMemberAnnotation a) { EmbeddedQueryExpression q = JdtQueryVisitorUtils.extractQueryExpression(a); if (q != null) { - computeSemanticTokens(jp, q.query().text(), q.query().offset(), q.isNative()).forEach(tokensData::accept); + computeSemanticTokens(jp, q.query(), q.isNative()).forEach(tokensData::accept); } return super.visit(a); } @@ -86,17 +87,22 @@ public class JdtDataQuerySemanticTokensProvider implements JdtSemanticTokensProv public boolean visit(MethodInvocation node) { EmbeddedQueryExpression q = JdtQueryVisitorUtils.extractQueryExpression(node); if (q != null) { - computeSemanticTokens(jp, q.query().text(), q.query().offset(), q.isNative()).forEach(tokensData::accept); + computeSemanticTokens(jp, q.query(), q.isNative()).forEach(tokensData::accept); } return super.visit(node); } }; } - public List computeSemanticTokens(IJavaProject jp, String query, int offset, boolean isNative) { - SemanticTokensDataProvider provider = isNative ? getSqlSemanticTokensProvider(jp) : (SpringProjectUtil.hasDependencyStartingWith(jp, "hibernate-core", null) ? hqlProvider : jpqlProvider); + public List computeSemanticTokens(IJavaProject jp, EmbeddedLanguageSnippet s, boolean isNative) { + SemanticTokensDataProvider provider = isNative ? getSqlSemanticTokensProvider(jp) + : (SpringProjectUtil.hasDependencyStartingWith(jp, "hibernate-core", null) ? hqlProvider + : jpqlProvider); if (provider != null) { - return provider.computeTokens(query, offset); + return provider.computeTokens(s.getText()).stream() + .flatMap(td -> s.toJavaRanges(td.range()).stream().map(r -> new SemanticTokenData(r, + td.type(), td.modifiers()))) + .toList(); } return Collections.emptyList(); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtQueryDocHighlightsProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtQueryDocHighlightsProvider.java index 68b6e2e32..c9bec05ac 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtQueryDocHighlightsProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtQueryDocHighlightsProvider.java @@ -54,9 +54,9 @@ public class JdtQueryDocHighlightsProvider implements JdtAstDocHighlightsProvide Collector collector = new Collector<>(); a.accept(semanticTokensProvider.getTokensComputer(project, doc, cu, collector)); for (SemanticTokenData t : collector.get()) { - if ("parameter".equals(t.type()) && t.start() <= offset && offset <= t.end()) { + if ("parameter".equals(t.type()) && t.range().getStart() <= offset && offset <= t.range().getEnd()) { try { - String parameterDescriptor = doc.get(t.start(), t.end() - t.start()); + String parameterDescriptor = doc.get(t.range().getOffset(), t.range().getLength()); SimpleName paramName = findParameter(m, parameterDescriptor); if (paramName != null) { DocumentHighlight highlight = new DocumentHighlight(); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtQueryVisitorUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtQueryVisitorUtils.java index ed93a516f..6aada6f67 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtQueryVisitorUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtQueryVisitorUtils.java @@ -18,24 +18,21 @@ import org.eclipse.jdt.core.dom.MemberValuePair; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.SingleMemberAnnotation; -import org.eclipse.jdt.core.dom.StringLiteral; -import org.eclipse.jdt.core.dom.TextBlock; import org.springframework.ide.vscode.boot.java.Annotations; import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchies; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLangAstUtils; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLanguageSnippet; public class JdtQueryVisitorUtils { private static final String QUERY = "Query"; private static final String NAMED_QUERY = "NamedQuery"; - - public record EmbeddedExpression(Expression expression, String text, int offset) {}; - - public record EmbeddedQueryExpression(EmbeddedExpression query, boolean isNative) {}; + public record EmbeddedQueryExpression(EmbeddedLanguageSnippet query, boolean isNative) {}; public static EmbeddedQueryExpression extractQueryExpression(SingleMemberAnnotation a) { if (isQueryAnnotation(a)) { - EmbeddedExpression expression = extractEmbeddedExpression(a.getValue()); + EmbeddedLanguageSnippet expression = EmbeddedLangAstUtils.extractEmbeddedExpression(a.getValue()); return expression == null ? null : new EmbeddedQueryExpression(expression, false); } return null; @@ -83,7 +80,7 @@ public class JdtQueryVisitorUtils { } } if (queryExpression != null) { - EmbeddedExpression e = extractEmbeddedExpression(queryExpression); + EmbeddedLanguageSnippet e = EmbeddedLangAstUtils.extractEmbeddedExpression(queryExpression); if (e != null) { return new EmbeddedQueryExpression(e, isNative); } @@ -96,7 +93,7 @@ public class JdtQueryVisitorUtils { IMethodBinding methodBinding = m.resolveMethodBinding(); if ("jakarta.persistence.EntityManager".equals(methodBinding.getDeclaringClass().getQualifiedName())) { if (methodBinding.getParameterTypes().length <= 2 && "java.lang.String".equals(methodBinding.getParameterTypes()[0].getQualifiedName())) { - EmbeddedExpression expression = extractEmbeddedExpression(queryExpr); + EmbeddedLanguageSnippet expression = EmbeddedLangAstUtils.extractEmbeddedExpression(queryExpr); return expression == null ? null : new EmbeddedQueryExpression(expression, false); } } @@ -104,22 +101,6 @@ public class JdtQueryVisitorUtils { return null; } - public static EmbeddedExpression extractEmbeddedExpression(Expression valueExp) { - String text = null; - int offset = 0; - if (valueExp instanceof StringLiteral sl) { - text = sl.getEscapedValue(); - text = text.substring(1, text.length() - 1); - offset = sl.getStartPosition() + 1; // +1 to skip over opening " - } else if (valueExp instanceof TextBlock tb) { - text = tb.getEscapedValue(); - text = text.substring(3, text.length() - 3); - offset = tb.getStartPosition() + 3; // +3 to skip over opening """ - } - return text == null ? null : new EmbeddedExpression(valueExp, text, offset); - } - - static boolean isQueryAnnotation(Annotation a) { if (Annotations.DATA_QUERY.equals(a.getTypeName().getFullyQualifiedName()) || QUERY.equals(a.getTypeName().getFullyQualifiedName())) { ITypeBinding type = a.resolveTypeBinding(); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JpqlSemanticTokens.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JpqlSemanticTokens.java index 99a1d7197..7dcafc47d 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JpqlSemanticTokens.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JpqlSemanticTokens.java @@ -35,6 +35,7 @@ import org.antlr.v4.runtime.tree.TerminalNode; import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensDataProvider; +import org.springframework.ide.vscode.commons.util.text.Region; import org.springframework.ide.vscode.parser.jpql.JpqlBaseListener; import org.springframework.ide.vscode.parser.jpql.JpqlLexer; import org.springframework.ide.vscode.parser.jpql.JpqlParser; @@ -77,7 +78,7 @@ public class JpqlSemanticTokens implements SemanticTokensDataProvider { } @Override - public List computeTokens(String text, int initialOffset) { + public List computeTokens(String text) { JpqlLexer lexer = new JpqlLexer(CharStreams.fromString(text)); CommonTokenStream antlrTokens = new CommonTokenStream(lexer); JpqlParser parser = new JpqlParser(antlrTokens); @@ -114,7 +115,7 @@ public class JpqlSemanticTokens implements SemanticTokensDataProvider { case JpqlParser.WS: break; case JpqlParser.SPEL: - tokens.addAll(computeTokensFromSpelNode(node, initialOffset, optSpelTokens)); + tokens.addAll(computeTokensFromSpelNode(node, 0, optSpelTokens)); break; default: if (JpqlParser.WS < type && type <= JpqlParser.WHERE) { @@ -201,8 +202,8 @@ public class JpqlSemanticTokens implements SemanticTokensDataProvider { parser.ql_statement(); semantics.entrySet().stream() - .map(e -> new SemanticTokenData(e.getKey().getStartIndex() + initialOffset, - e.getKey().getStartIndex() + e.getKey().getText().length() + initialOffset, e.getValue(), + .map(e -> new SemanticTokenData(e.getKey().getStartIndex(), + e.getKey().getStartIndex() + e.getKey().getText().length(), e.getValue(), new String[0])) .forEach(tokens::add); @@ -222,10 +223,14 @@ public class JpqlSemanticTokens implements SemanticTokensDataProvider { spelTokens.add(new SemanticTokenData(startPosition, spelStartPosition, "operator", new String[0])); // SPEL contents optSpelTokens.ifPresentOrElse( - spelTokenProvider -> spelTokens - .addAll(spelTokenProvider.computeTokens(node.getText().substring(2, node.getText().length() - 1), spelStartPosition)), - () -> spelTokens.add(new SemanticTokenData(spelStartPosition, spelEndPosition, "string", new String[0]))); - + spelTokenProvider -> spelTokens.addAll(spelTokenProvider + .computeTokens(node.getText().substring(2, node.getText().length() - 1)).stream() + .map(td -> new SemanticTokenData(new Region(td.range().getOffset() + spelStartPosition, td.range().getLength()), + td.type(), td.modifiers())) + .toList()), + () -> spelTokens + .add(new SemanticTokenData(spelStartPosition, spelEndPosition, "string", new String[0]))); + // '}' operator spelTokens.add(new SemanticTokenData(spelEndPosition, endPosition, "operator", new String[0])); return spelTokens; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/MySqlSemanticTokens.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/MySqlSemanticTokens.java index 2d462ec97..576543ee6 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/MySqlSemanticTokens.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/MySqlSemanticTokens.java @@ -33,6 +33,7 @@ import org.antlr.v4.runtime.atn.ATNConfigSet; import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.tree.ErrorNode; import org.antlr.v4.runtime.tree.TerminalNode; +import org.springframework.ide.vscode.boot.java.embadded.lang.AntlrUtils; import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensDataProvider; @@ -72,7 +73,7 @@ public class MySqlSemanticTokens implements SemanticTokensDataProvider { } @Override - public List computeTokens(String text, int initialOffset) { + public List computeTokens(String text) { MySqlLexer lexer = new MySqlLexer(CharStreams.fromString(text)); CommonTokenStream antlrTokens = new CommonTokenStream(lexer); MySqlParser parser = new MySqlParser(antlrTokens); @@ -90,7 +91,7 @@ public class MySqlSemanticTokens implements SemanticTokensDataProvider { int type = node.getSymbol().getType(); switch (type) { case MySqlParser.SPEL: - tokens.addAll(JpqlSemanticTokens.computeTokensFromSpelNode(node, initialOffset, optSpelTokens)); + tokens.addAll(JpqlSemanticTokens.computeTokensFromSpelNode(node, 0, optSpelTokens)); break; case MySqlParser.ID: semantics.put(node.getSymbol(), "variable"); @@ -255,17 +256,17 @@ public class MySqlSemanticTokens implements SemanticTokensDataProvider { if (e.getKey().getType() == MySqlLexer.DOT_ID) { return Stream.of( // the prefix '.' is an operator - new SemanticTokenData(startIndex + initialOffset, - startIndex + 1 + initialOffset, "operator", + new SemanticTokenData(startIndex, + startIndex + 1, "operator", new String[0]), // the rest whatever it was meant to be initially - new SemanticTokenData(startIndex + 1 + initialOffset, - startIndex + e.getKey().getText().length() + initialOffset, e.getValue(), + new SemanticTokenData(startIndex + 1, + startIndex + e.getKey().getText().length(), e.getValue(), new String[0]) ); } else { - return Stream.of(new SemanticTokenData(startIndex + initialOffset, - startIndex + e.getKey().getText().length() + initialOffset, e.getValue(), + return Stream.of(new SemanticTokenData(startIndex, + startIndex + e.getKey().getText().length(), e.getValue(), new String[0])); } }) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/NamedQueryPropertiesReconcileEngine.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/NamedQueryPropertiesReconcileEngine.java index 0026a9693..56447361d 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/NamedQueryPropertiesReconcileEngine.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/NamedQueryPropertiesReconcileEngine.java @@ -17,6 +17,7 @@ import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFin import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector; import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine; import org.springframework.ide.vscode.commons.util.text.IDocument; +import org.springframework.ide.vscode.commons.util.text.Region; import org.springframework.ide.vscode.java.properties.antlr.parser.AntlrParser; import org.springframework.ide.vscode.java.properties.parser.ParseResults; import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.KeyValuePair; @@ -45,7 +46,7 @@ public class NamedQueryPropertiesReconcileEngine implements IReconcileEngine { ParseResults parseResults = parser.parse(doc.get()); for (KeyValuePair pair : parseResults.ast.getPropertyValuePairs()) { Value value = pair.getValue(); - reconciler.reconcile(value.decode(), value.getOffset(), problemCollector); + reconciler.reconcile(value.decode(), r -> new Region(r.getOffset() + value.getOffset(), r.getLength()), problemCollector); } } finally { problemCollector.endCollecting(); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokens.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokens.java index 083714bc5..f27dcf511 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokens.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokens.java @@ -32,6 +32,7 @@ import org.antlr.v4.runtime.atn.ATNConfigSet; import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.tree.ErrorNode; import org.antlr.v4.runtime.tree.TerminalNode; +import org.springframework.ide.vscode.boot.java.embadded.lang.AntlrUtils; import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensDataProvider; @@ -73,7 +74,7 @@ public class PostgreSqlSemanticTokens implements SemanticTokensDataProvider { } @Override - public List computeTokens(String text, int initialOffset) { + public List computeTokens(String text) { PostgreSqlLexer lexer = new PostgreSqlLexer(CharStreams.fromString(text)); CommonTokenStream antlrTokens = new CommonTokenStream(lexer); PostgreSqlParser parser = new PostgreSqlParser(antlrTokens); @@ -109,7 +110,7 @@ public class PostgreSqlSemanticTokens implements SemanticTokensDataProvider { } else if (type >= PostgreSqlLexer.LineComment && type <= PostgreSqlLexer.UnterminatedBlockComment) { semantics.put(token, "comment"); } else if (type == PostgreSqlLexer.SPEL) { - tokens.addAll(JpqlSemanticTokens.computeTokensFromSpelNode(node, initialOffset, optSpelTokens)); + tokens.addAll(JpqlSemanticTokens.computeTokensFromSpelNode(node, 0, optSpelTokens)); } } @@ -181,8 +182,8 @@ public class PostgreSqlSemanticTokens implements SemanticTokensDataProvider { parser.root(); semantics.entrySet().stream() - .map(e -> new SemanticTokenData(e.getKey().getStartIndex() + initialOffset, - e.getKey().getStartIndex() + e.getKey().getText().length() + initialOffset, e.getValue(), + .map(e -> new SemanticTokenData(e.getKey().getStartIndex(), + e.getKey().getStartIndex() + e.getKey().getText().length(), e.getValue(), new String[0])) .forEach(tokens::add); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/QueryJdtAstReconciler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/QueryJdtAstReconciler.java index bea37b4e8..ff95de3c5 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/QueryJdtAstReconciler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/QueryJdtAstReconciler.java @@ -17,13 +17,11 @@ import java.util.Optional; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.SingleMemberAnnotation; -import org.eclipse.jdt.core.dom.StringLiteral; -import org.eclipse.jdt.core.dom.TextBlock; import org.springframework.ide.vscode.boot.java.data.jpa.queries.JdtQueryVisitorUtils.EmbeddedQueryExpression; +import org.springframework.ide.vscode.boot.java.embadded.lang.AntlrReconcilerWithSpel; import org.springframework.ide.vscode.boot.java.handlers.Reconciler; import org.springframework.ide.vscode.boot.java.reconcilers.JdtAstReconciler; import org.springframework.ide.vscode.boot.java.reconcilers.RequiredCompleteAstException; @@ -63,7 +61,7 @@ public class QueryJdtAstReconciler implements JdtAstReconciler { EmbeddedQueryExpression q = JdtQueryVisitorUtils.extractQueryExpression(node); if (q != null) { Optional reconcilerOpt = q.isNative() ? getSqlReconciler(project) : Optional.of(getQueryReconciler(project)); - reconcilerOpt.ifPresent(r -> r.reconcile(q.query().text(), q.query().offset(), problemCollector)); + reconcilerOpt.ifPresent(r -> r.reconcile(q.query().getText(), q.query()::toSingleJavaRange, problemCollector)); } return super.visit(node); } @@ -72,7 +70,7 @@ public class QueryJdtAstReconciler implements JdtAstReconciler { public boolean visit(SingleMemberAnnotation node) { EmbeddedQueryExpression q = JdtQueryVisitorUtils.extractQueryExpression(node); if (q != null) { - getQueryReconciler(project).reconcile(q.query().text(), q.query().offset(), problemCollector); + getQueryReconciler(project).reconcile(q.query().getText(), q.query()::toSingleJavaRange, problemCollector); } return super.visit(node); } @@ -81,7 +79,7 @@ public class QueryJdtAstReconciler implements JdtAstReconciler { public boolean visit(MethodInvocation node) { EmbeddedQueryExpression q = JdtQueryVisitorUtils.extractQueryExpression(node); if (q != null) { - getQueryReconciler(project).reconcile(q.query().text(), q.query().offset(), problemCollector); + getQueryReconciler(project).reconcile(q.query().getText(), q.query()::toSingleJavaRange, problemCollector); } return super.visit(node); } @@ -96,23 +94,23 @@ public class QueryJdtAstReconciler implements JdtAstReconciler { return SpringProjectUtil.hasDependencyStartingWith(project, "hibernate-core", null) ? hqlReconciler : jpqlReconciler; } - public static void reconcileExpression(Reconciler reconciler, Expression valueExp, IProblemCollector problemCollector) { - String query = null; - int offset = 0; - if (valueExp instanceof StringLiteral sl) { - query = sl.getEscapedValue(); - query = query.substring(1, query.length() - 1); - offset = sl.getStartPosition() + 1; // +1 to skip over opening " - } else if (valueExp instanceof TextBlock tb) { - query = tb.getEscapedValue(); - query = query.substring(3, query.length() - 3); - offset = tb.getStartPosition() + 3; // +3 to skip over opening """ - } - - if (query != null) { - reconciler.reconcile(query, offset, problemCollector); - } - } +// public static void reconcileExpression(Reconciler reconciler, Expression valueExp, IProblemCollector problemCollector) { +// String query = null; +// int offset = 0; +// if (valueExp instanceof StringLiteral sl) { +// query = sl.getEscapedValue(); +// query = query.substring(1, query.length() - 1); +// offset = sl.getStartPosition() + 1; // +1 to skip over opening " +// } else if (valueExp instanceof TextBlock tb) { +// query = tb.getEscapedValue(); +// query = query.substring(3, query.length() - 3); +// offset = tb.getStartPosition() + 3; // +3 to skip over opening """ +// } +// +// if (query != null) { +// reconciler.reconcile(query, offset, problemCollector); +// } +// } @Override public boolean isApplicable(IJavaProject project) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/QueryPropertiesSemanticTokensHandler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/QueryPropertiesSemanticTokensHandler.java index cec4bed21..d71b11829 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/QueryPropertiesSemanticTokensHandler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/QueryPropertiesSemanticTokensHandler.java @@ -27,6 +27,7 @@ import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.Sem import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensDataProvider; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensHandler; import org.springframework.ide.vscode.commons.util.text.LanguageId; +import org.springframework.ide.vscode.commons.util.text.Region; import org.springframework.ide.vscode.commons.util.text.TextDocument; import org.springframework.ide.vscode.java.properties.antlr.parser.AntlrParser; import org.springframework.ide.vscode.java.properties.parser.ParseResults; @@ -76,7 +77,9 @@ public class QueryPropertiesSemanticTokensHandler implements SemanticTokensHandl for (PropertiesAst.KeyValuePair node : result.ast.getPropertyValuePairs()) { Value value = node.getValue(); if (value != null) { - data.addAll(tokensProvider.computeTokens(value.decode(), value.getOffset())); + tokensProvider.computeTokens(value.decode()).stream() + .map(td -> new SemanticTokenData(new Region(td.range().getOffset() + value.getOffset(), td.range().getLength()), td.type(), td.modifiers())) + .forEach(data::add); } } return data; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/AntlrReconciler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/AntlrReconciler.java similarity index 87% rename from headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/AntlrReconciler.java rename to headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/AntlrReconciler.java index f8e152b87..148151436 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/AntlrReconciler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/AntlrReconciler.java @@ -8,10 +8,11 @@ * Contributors: * Broadcom, Inc. - initial API and implementation *******************************************************************************/ -package org.springframework.ide.vscode.boot.java.data.jpa.queries; +package org.springframework.ide.vscode.boot.java.embadded.lang; import java.util.BitSet; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; import org.antlr.v4.runtime.ANTLRErrorListener; import org.antlr.v4.runtime.CharStream; @@ -33,6 +34,8 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemC import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType; import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl; import org.springframework.ide.vscode.commons.util.BadLocationException; +import org.springframework.ide.vscode.commons.util.text.IRegion; +import org.springframework.ide.vscode.commons.util.text.Region; import org.springframework.ide.vscode.commons.util.text.linetracker.DefaultLineTracker; public class AntlrReconciler implements Reconciler { @@ -57,7 +60,7 @@ public class AntlrReconciler implements Reconciler { this.problemType = problemType; } - protected Parser createParser(String text, int startPosition, IProblemCollector problemCollector) throws Exception { + protected Parser createParser(String text, Function mapping, IProblemCollector problemCollector) throws Exception { Lexer lexer = lexerClass.getDeclaredConstructor(CharStream.class).newInstance(CharStreams.fromString(text)); CommonTokenStream antlrTokens = new CommonTokenStream(lexer); Parser parser = parserClass.getDeclaredConstructor(TokenStream.class).newInstance(antlrTokens); @@ -93,7 +96,8 @@ public class AntlrReconciler implements Reconciler { log.error("", e1); } } - problemCollector.accept(new ReconcileProblemImpl(problemType, String.format("%s: %s", prefix, msg), startPosition + offset, length)); + IRegion problemRegion = mapping.apply(new Region(offset, length)); + problemCollector.accept(new ReconcileProblemImpl(problemType, String.format("%s: %s", prefix, msg), problemRegion.getOffset(), problemRegion.getLength())); } @Override @@ -121,9 +125,9 @@ public class AntlrReconciler implements Reconciler { } @Override - public void reconcile(String text, int startPosition, IProblemCollector problemCollector) { + public void reconcile(String text, Function mapping, IProblemCollector problemCollector) { try { - Parser parser = createParser(text, startPosition, problemCollector); + Parser parser = createParser(text, mapping, problemCollector); parserClass.getDeclaredMethod(parseMethod).invoke(parser); } catch (Throwable t) { log.error("", t); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/AntlrReconcilerWithSpel.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/AntlrReconcilerWithSpel.java similarity index 74% rename from headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/AntlrReconcilerWithSpel.java rename to headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/AntlrReconcilerWithSpel.java index 19f67d33f..8dacf1a8d 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/AntlrReconcilerWithSpel.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/AntlrReconcilerWithSpel.java @@ -8,9 +8,10 @@ * Contributors: * Broadcom, Inc. - initial API and implementation *******************************************************************************/ -package org.springframework.ide.vscode.boot.java.data.jpa.queries; +package org.springframework.ide.vscode.boot.java.embadded.lang; import java.util.Optional; +import java.util.function.Function; import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.Parser; @@ -21,6 +22,8 @@ import org.antlr.v4.runtime.tree.TerminalNode; import org.springframework.ide.vscode.boot.java.spel.SpelReconciler; import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector; import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType; +import org.springframework.ide.vscode.commons.util.text.IRegion; +import org.springframework.ide.vscode.commons.util.text.Region; public class AntlrReconcilerWithSpel extends AntlrReconciler { @@ -35,15 +38,15 @@ public class AntlrReconcilerWithSpel extends AntlrReconciler { } @Override - protected Parser createParser(String text, int startPosition, IProblemCollector problemCollector) throws Exception { - Parser parser = super.createParser(text, startPosition, problemCollector); + protected Parser createParser(String text, Function mapping, IProblemCollector problemCollector) throws Exception { + Parser parser = super.createParser(text, mapping, problemCollector); // Reconcile embedded SPEL spelReconciler.ifPresent(r -> parser.addParseListener(new ParseTreeListener() { private void processTerminal(TerminalNode node) { if (node.getSymbol().getType() == spelTokenType) { - AntlrReconcilerWithSpel.reconcileEmbeddedSpelNode(node, startPosition, r, problemCollector); + AntlrReconcilerWithSpel.reconcileEmbeddedSpelNode(node, mapping, r, problemCollector); } } @@ -70,10 +73,9 @@ public class AntlrReconcilerWithSpel extends AntlrReconciler { return parser; } - private static void reconcileEmbeddedSpelNode(TerminalNode node, int initialOffset, SpelReconciler spelReconciler, IProblemCollector problemCollector) { - int startPosition = initialOffset + node.getSymbol().getStartIndex(); + private static void reconcileEmbeddedSpelNode(TerminalNode node, Function mapping, SpelReconciler spelReconciler, IProblemCollector problemCollector) { String spelContent = node.getSymbol().getText().substring(2, node.getSymbol().getText().length() - 1); - spelReconciler.reconcile(spelContent, startPosition, problemCollector); + spelReconciler.reconcile(spelContent, r -> new Region(r.getOffset() + node.getSymbol().getStartIndex(), r.getLength())/*i -> mapping.apply(i + node.getSymbol().getStartIndex())*/, problemCollector); } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/AntlrUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/AntlrUtils.java similarity index 94% rename from headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/AntlrUtils.java rename to headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/AntlrUtils.java index 799e66c8b..c5f475330 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/AntlrUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/AntlrUtils.java @@ -8,7 +8,7 @@ * Contributors: * Broadcom, Inc. - initial API and implementation *******************************************************************************/ -package org.springframework.ide.vscode.boot.java.data.jpa.queries; +package org.springframework.ide.vscode.boot.java.embadded.lang; import java.util.stream.Stream; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/CompositeEmbeddedLanguageSnippet.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/CompositeEmbeddedLanguageSnippet.java new file mode 100644 index 000000000..d8248e842 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/CompositeEmbeddedLanguageSnippet.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.embadded.lang; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Map.Entry; +import java.util.TreeMap; + +import org.springframework.ide.vscode.commons.util.text.IRegion; +import org.springframework.ide.vscode.commons.util.text.Region; + +public class CompositeEmbeddedLanguageSnippet implements EmbeddedLanguageSnippet { + + private TreeMap snippetParts; + private String text; + + public CompositeEmbeddedLanguageSnippet(Collection snippets) { + snippetParts = new TreeMap<>(new Comparator() { + + @Override + public int compare(IRegion o1, IRegion o2) { + return o1.getOffset() - o2.getOffset(); + } + + }); + StringBuilder sb = new StringBuilder(); + int offset = 0; + for (EmbeddedLanguageSnippet s : snippets) { + String t = s.getText(); + sb.append(t); + snippetParts.putIfAbsent(new Region(offset, t.length()), s); + offset += t.length(); + } + this.text = sb.toString(); + } + + @Override + public List toJavaRanges(IRegion range) { + List javaRegions = new ArrayList<>(); + Entry startEntry = snippetParts.floorEntry(new Region(range.getStart(), 0)); + Entry endEntry = snippetParts.floorEntry(new Region(range.getEnd(), 0)); + + + if (startEntry.getKey().equals(endEntry.getKey())) { + // The Range is within the same snippet piece + javaRegions.addAll(startEntry.getValue().toJavaRanges(new Region(range.getOffset() - startEntry.getKey().getOffset(), range.getLength()))); + } else { + // The range spans a number of snippets + // starting snippet - part of it should be included + int offset = range.getOffset() - startEntry.getKey().getOffset(); + int length = startEntry.getKey().getLength() - offset; + if (length > 0) { + javaRegions.addAll(startEntry.getValue().toJavaRanges(new Region(offset, length))); + } + // snippet parts entirely in the request range - entire snippet range is included + for (Entry e : snippetParts.subMap(startEntry.getKey(), false, endEntry.getKey(), false).entrySet()) { + javaRegions.addAll(e.getValue().toJavaRanges(new Region(0, e.getKey().getLength()))); + } + // ending snippet - part of it should be included + offset = 0; + length = range.getEnd() - endEntry.getKey().getOffset(); + if (length > 0) { + javaRegions.addAll(endEntry.getValue().toJavaRanges(new Region(offset, length))); + } + + } + return javaRegions; + } + + @Override + public int toJavaOffset(int offset) { + Entry entry = snippetParts.floorEntry(new Region(offset, 0)); + return entry.getValue().toJavaOffset(offset - entry.getKey().getOffset()); + } + + @Override + public String getText() { + return text; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLangAstUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLangAstUtils.java new file mode 100644 index 000000000..6d04976a0 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLangAstUtils.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.embadded.lang; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.InfixExpression; +import org.eclipse.jdt.core.dom.StringLiteral; +import org.eclipse.jdt.core.dom.TextBlock; + +public class EmbeddedLangAstUtils { + + public static EmbeddedLanguageSnippet extractEmbeddedExpression(Expression valueExp) { + if (valueExp instanceof StringLiteral sl) { + return new StringLiteralLanguageSnippet(sl); + } else if (valueExp instanceof TextBlock tb) { + return new TextBlockLanguageSnippet(tb); + } else if (valueExp instanceof InfixExpression ie && ie.getOperator() == InfixExpression.Operator.PLUS) { + EmbeddedLanguageSnippet leftSnippet = extractEmbeddedExpression(ie.getLeftOperand()); + List snippets = new ArrayList<>(2 + ie.extendedOperands().size()); + if (leftSnippet == null) { + return null; + } else { + snippets.add(leftSnippet); + } + EmbeddedLanguageSnippet rightSnippet = extractEmbeddedExpression(ie.getRightOperand()); + if (rightSnippet == null) { + return null; + } else { + snippets.add(rightSnippet); + } + for (Object o : ie.extendedOperands()) { + if (o instanceof Expression exp) { + EmbeddedLanguageSnippet s = extractEmbeddedExpression(exp); + if (s == null) { + return null; + } else { + snippets.add(s); + } + } + } + return new CompositeEmbeddedLanguageSnippet(snippets); + } + return null; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLanguageSnippet.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLanguageSnippet.java new file mode 100644 index 000000000..e3f082100 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLanguageSnippet.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.embadded.lang; + +import java.util.List; + +import org.springframework.ide.vscode.commons.util.text.IRegion; +import org.springframework.ide.vscode.commons.util.text.Region; + +public interface EmbeddedLanguageSnippet { + + List toJavaRanges(IRegion range); + + default IRegion toSingleJavaRange(IRegion range) { + List ranges = toJavaRanges(range); + int start = ranges.get(0).getOffset(); + int end = ranges.get(ranges.size() - 1).getEnd(); + return new Region(start, end - start); + } + + int toJavaOffset(int offset); + + String getText(); + + default IRegion getTotalRange() { + return toSingleJavaRange(new Region(0, getText().length())); + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLanguageSnippetWithPrefixAndSuffix.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLanguageSnippetWithPrefixAndSuffix.java new file mode 100644 index 000000000..79e76daeb --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/EmbeddedLanguageSnippetWithPrefixAndSuffix.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.embadded.lang; + +import java.util.List; + +import org.springframework.ide.vscode.commons.util.text.IRegion; +import org.springframework.ide.vscode.commons.util.text.Region; + +public class EmbeddedLanguageSnippetWithPrefixAndSuffix implements EmbeddedLanguageSnippet { + + private final EmbeddedLanguageSnippet snippet; + private final int start; + private final int end; + + public EmbeddedLanguageSnippetWithPrefixAndSuffix(EmbeddedLanguageSnippet snippet, int start, int end) { + this.snippet = snippet; + this.start = start; + this.end = end; + } + + @Override + public String getText() { + return snippet.getText().substring(start, end); + } + + @Override + public List toJavaRanges(IRegion range) { + return snippet.toJavaRanges(new Region(range.getOffset() + start, range.getLength())); + } + + @Override + public int toJavaOffset(int offset) { + return snippet.toJavaOffset(offset + start); + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/StringLiteralLanguageSnippet.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/StringLiteralLanguageSnippet.java new file mode 100644 index 000000000..389465a38 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/StringLiteralLanguageSnippet.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.embadded.lang; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.core.dom.StringLiteral; +import org.springframework.ide.vscode.commons.util.text.IRegion; +import org.springframework.ide.vscode.commons.util.text.Region; + +public class StringLiteralLanguageSnippet implements EmbeddedLanguageSnippet { + + final private int literalOffset; + final private String escapedValue; + final private String literalValue; + + private transient int startOffset; + /* + * Each region represents a tuple where: + * - offset is the position in the snippet text. + * - length is the number of chars symbol at that location takes in the escaped snippet text + */ + private transient List specialRegions; + + public StringLiteralLanguageSnippet(StringLiteral literal) { + this(literal.getEscapedValue(), literal.getLiteralValue(), literal.getStartPosition()); + } + + public StringLiteralLanguageSnippet(String escapedValue, String literalValue, int literalOffset) { + this.escapedValue = escapedValue; + this.literalValue = literalValue; + this.literalOffset = literalOffset; + } + + @Override + public int toJavaOffset(int offset) { + if (specialRegions == null) { + specialRegions = createMappings(); + } + int mappedOffset = literalOffset + startOffset + offset; + for (Region r : specialRegions) { + if (offset > r.getStart()) { + // length - 1 because 1 is added implicitly from '+ offset' above. Length of char escaped or not is >= 1 + mappedOffset += (r.getLength() - 1); + } else { + break; + } + } + return mappedOffset; + } + + @Override + public List toJavaRanges(IRegion range) { + int start = toJavaOffset(range.getStart()); + int end = toJavaOffset(range.getEnd()); + return List.of(new Region(start, end - start)); + } + + @Override + public String getText() { + return literalValue; + } + + private List createMappings() { + List regions = new ArrayList<>(); + if (literalValue.length() > 0) { + int current = 1; // skip over opening " + startOffset = current; + boolean escaping = false; + // <= to include the next char after the end of the literal actual value + for (int i = 0; i <= literalValue.length();) { + if (escaping) { + regions.add(new Region(i, 2)); + i++; + current++; + escaping = false; + } else { + if (escapedValue.charAt(current) == '\\') { + escaping = escapedValue.charAt(current) == '\\'; + current++; + } else { + i++; + current++; + } + } + } + } + return regions; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/TextBlockLanguageSnippet.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/TextBlockLanguageSnippet.java new file mode 100644 index 000000000..061166530 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/embadded/lang/TextBlockLanguageSnippet.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2024 Broadcom, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.embadded.lang; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.core.dom.TextBlock; +import org.springframework.ide.vscode.commons.util.text.IRegion; +import org.springframework.ide.vscode.commons.util.text.Region; + +public class TextBlockLanguageSnippet implements EmbeddedLanguageSnippet { + + final private int literalOffset; + final private String escapedValue; + final private String literalValue; + + private transient int startOffset; + private transient List specialRegions; + + public TextBlockLanguageSnippet(TextBlock block) { + this(block.getEscapedValue(), block.getLiteralValue(), block.getStartPosition()); + } + + public TextBlockLanguageSnippet(String escapedValue, String literalValue, int literalOffset) { + this.escapedValue = escapedValue; + this.literalValue = literalValue; + this.literalOffset = literalOffset; + } + + @Override + public List toJavaRanges(IRegion range) { + int start = toJavaOffset(range.getStart()); + int end = toJavaOffset(range.getEnd()); + return List.of(new Region(start, end - start)); + } + + @Override + public int toJavaOffset(int offset) { + if (specialRegions == null) { + specialRegions = createMappings(); + } + int mappedOffset = literalOffset + startOffset + offset; + for (Region r : specialRegions) { + if (offset > r.getStart()) { + // length - 1 because 1 is added implicitly from '+ offset' above. Length of char escaped or not is >= 1 + mappedOffset += (r.getLength() - 1); + } + } + return mappedOffset; + } + + @Override + public String getText() { + return literalValue; + } + + private List createMappings() { + List regions = new ArrayList<>(); + if (literalValue.length() > 0) { + int current = 3; // skip over opening """ + for (; current < escapedValue.length() && escapedValue.charAt(current) != '\\' && escapedValue.charAt(current) != literalValue.charAt(0); current++) { + + } + startOffset = current; + boolean escaping = escapedValue.charAt(current) == '\\'; + // <= to include the next char after the end of the literal actual value + for (int i = 0; i <= literalValue.length();) { + if (escaping) { + regions.add(new Region(i, 2)); + i++; + current++; + escaping = false; + } else { + if (escapedValue.charAt(current) == '\\') { + escaping = escapedValue.charAt(current) == '\\'; + current++; + } else { + i++; + current++; + } + } + } + } + return regions; + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/CopilotCodeLensProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/CopilotCodeLensProvider.java index d1bc341e6..c798a9286 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/CopilotCodeLensProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/CopilotCodeLensProvider.java @@ -38,8 +38,8 @@ import org.eclipse.lsp4j.jsonrpc.CancelChecker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.boot.java.Annotations; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLanguageSnippet; import org.springframework.ide.vscode.boot.java.spel.AnnotationParamSpelExtractor; -import org.springframework.ide.vscode.boot.java.spel.AnnotationParamSpelExtractor.Snippet; import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.SpringProjectUtil; @@ -47,6 +47,7 @@ import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFin import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData; import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; import org.springframework.ide.vscode.commons.util.BadLocationException; +import org.springframework.ide.vscode.commons.util.text.IRegion; import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.collect.ImmutableList; @@ -99,7 +100,7 @@ public class CopilotCodeLensProvider implements CodeLensProvider { public boolean visit(SingleMemberAnnotation node) { Arrays.stream(spelExtractors).map(e -> e.getSpelRegion(node)).filter(o -> o.isPresent()) .map(o -> o.get()).forEach(snippet -> { - String additionalContext = parseSpelAndFetchContext(cu, snippet.text()); + String additionalContext = parseSpelAndFetchContext(cu, snippet.getText()); provideCodeLensForSpelExpression(cancelToken, node, document, snippet, additionalContext, resultAccumulator); }); @@ -119,7 +120,7 @@ public class CopilotCodeLensProvider implements CodeLensProvider { Arrays.stream(spelExtractors).map(e -> e.getSpelRegion(node)).filter(o -> o.isPresent()) .map(o -> o.get()).forEach(snippet -> { - String additionalContext = parseSpelAndFetchContext(cu, snippet.text()); + String additionalContext = parseSpelAndFetchContext(cu, snippet.getText()); provideCodeLensForSpelExpression(cancelToken, node, document, snippet, additionalContext, resultAccumulator); }); @@ -154,7 +155,7 @@ public class CopilotCodeLensProvider implements CodeLensProvider { } protected void provideCodeLensForSpelExpression(CancelChecker cancelToken, Annotation node, TextDocument document, - Snippet snippet, String additionalContext, List resultAccumulator) { + EmbeddedLanguageSnippet snippet, String additionalContext, List resultAccumulator) { cancelToken.checkCanceled(); if (snippet != null) { @@ -167,12 +168,13 @@ public class CopilotCodeLensProvider implements CodeLensProvider { """,additionalContext) : ""; CodeLens codeLens = new CodeLens(); - codeLens.setRange(document.toRange(snippet.offset(), snippet.text().length())); + IRegion totalRange = snippet.getTotalRange(); + codeLens.setRange(document.toRange(totalRange.getStart(), totalRange.getLength())); Command cmd = new Command(); cmd.setTitle(QueryType.SPEL.getTitle()); cmd.setCommand(CMD); - cmd.setArguments(ImmutableList.of(QueryType.SPEL.getPrompt() + snippet.text() + "\n\n" + context)); + cmd.setArguments(ImmutableList.of(QueryType.SPEL.getPrompt() + snippet.getText() + "\n\n" + context)); codeLens.setCommand(cmd); resultAccumulator.add(codeLens); @@ -235,7 +237,7 @@ public class CopilotCodeLensProvider implements CodeLensProvider { private List parseSpelExpression(String spelText) { try { - return spelSemanticTokens.computeTokens(spelText, 0); + return spelSemanticTokens.computeTokens(spelText); } catch (Exception e) { logger.error("Error computing tokens: " + e.getMessage()); return Collections.emptyList(); @@ -244,7 +246,7 @@ public class CopilotCodeLensProvider implements CodeLensProvider { private static Set extractMethodNames(List tokens, String spelText) { return tokens.stream().filter(token -> "method".equals(token.type())) - .map(token -> spelText.substring(token.start(), token.end())).collect(Collectors.toSet()); + .map(token -> spelText.substring(token.range().getStart(), token.range().getEnd())).collect(Collectors.toSet()); } private List collectMethodContexts(Set methodNames, CompilationUnit cu) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/Reconciler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/Reconciler.java index 40109c3a2..6a82f71ec 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/Reconciler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/Reconciler.java @@ -10,13 +10,16 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.handlers; +import java.util.function.Function; + import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector; +import org.springframework.ide.vscode.commons.util.text.IRegion; /** * @author Martin Lippert */ public interface Reconciler { - void reconcile(String value, int startPosition, IProblemCollector problemCollector); + void reconcile(String value, Function offsetMapper, IProblemCollector problemCollector); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/SpelExpressionReconciler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/SpelExpressionReconciler.java index c290b0004..ca2df6c42 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/SpelExpressionReconciler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/SpelExpressionReconciler.java @@ -10,12 +10,16 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.handlers; +import java.util.function.Function; + import org.springframework.expression.ParseException; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.ide.vscode.boot.java.SpelProblemType; import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector; import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem; import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl; +import org.springframework.ide.vscode.commons.util.text.IRegion; +import org.springframework.ide.vscode.commons.util.text.Region; import org.springframework.util.SystemPropertyUtils; /** @@ -34,7 +38,7 @@ public class SpelExpressionReconciler implements Reconciler { } @Override - public void reconcile(String spelExpression, int startPosition, IProblemCollector problemCollector) { + public void reconcile(String spelExpression, Function mapper, IProblemCollector problemCollector) { if (!this.spelExpressionValidationEnabled) { return; } @@ -47,17 +51,11 @@ public class SpelExpressionReconciler implements Reconciler { catch (ParseException e) { String message = e.getSimpleMessage(); int position = e.getPosition(); - - createProblem(spelExpression, message, startPosition, position, problemCollector); + IRegion r = mapper.apply(new Region(0, position)); + ReconcileProblem problem = new ReconcileProblemImpl(SpelProblemType.JAVA_SPEL_EXPRESSION_SYNTAX, message, r.getOffset(), r.getLength()); + problemCollector.accept(problem); } } } - private void createProblem(String spelExpression, String message, int startPosition, int position, IProblemCollector problemCollector) { - int start = startPosition + position; - int length = spelExpression.length() - position; - ReconcileProblem problem = new ReconcileProblemImpl(SpelProblemType.JAVA_SPEL_EXPRESSION_SYNTAX, message, start, length); - problemCollector.accept(problem); - } - } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/AnnotationParamSpelExtractor.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/AnnotationParamSpelExtractor.java index 01ce086ce..cfc9ee3dc 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/AnnotationParamSpelExtractor.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/AnnotationParamSpelExtractor.java @@ -17,9 +17,11 @@ import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.MemberValuePair; import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.SingleMemberAnnotation; -import org.eclipse.jdt.core.dom.StringLiteral; import org.springframework.ide.vscode.boot.java.Annotations; import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchies; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLangAstUtils; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLanguageSnippet; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLanguageSnippetWithPrefixAndSuffix; public final class AnnotationParamSpelExtractor { @@ -87,7 +89,7 @@ public final class AnnotationParamSpelExtractor { this.prefixSuffixes = List.of(new PrefixSuffix(paramValuePrefix, paramValueSuffx), new PrefixSuffix("", "")); } - public Optional getSpelRegion(NormalAnnotation a) { + public Optional getSpelRegion(NormalAnnotation a) { if (paramName == null) { return Optional.empty(); } @@ -104,8 +106,9 @@ public final class AnnotationParamSpelExtractor { String name = pair.getName().getFullyQualifiedName(); if (name != null && name.equals(paramName)) { Expression expression = pair.getValue(); - if (expression instanceof StringLiteral) { - return fromStringLiteral((StringLiteral) expression); + EmbeddedLanguageSnippet embeddedSnippet = EmbeddedLangAstUtils.extractEmbeddedExpression(expression); + if (embeddedSnippet != null) { + return fromEmbeddedSnippet(embeddedSnippet); } } } @@ -114,7 +117,7 @@ public final class AnnotationParamSpelExtractor { return Optional.empty(); } - public Optional getSpelRegion(SingleMemberAnnotation a) { + public Optional getSpelRegion(SingleMemberAnnotation a) { if (this.paramName != null) { return Optional.empty(); } @@ -124,26 +127,24 @@ public final class AnnotationParamSpelExtractor { } Expression valueExp = a.getValue(); - - if (valueExp instanceof StringLiteral) { - return fromStringLiteral((StringLiteral) valueExp); - } + EmbeddedLanguageSnippet embeddedSnippet = EmbeddedLangAstUtils.extractEmbeddedExpression(valueExp); + if (embeddedSnippet != null) { + return fromEmbeddedSnippet(embeddedSnippet); + } + return Optional.empty(); } - private Optional fromStringLiteral(StringLiteral valueExp) { - String value = valueExp.getEscapedValue(); - value = value.substring(1, value.length() - 1); - if (value != null) { + private Optional fromEmbeddedSnippet(EmbeddedLanguageSnippet embeddedSnippet) { + String value = embeddedSnippet.getText(); + if (value != null && !value.isBlank()) { for (PrefixSuffix ps : prefixSuffixes) { int startIdx = value.indexOf(ps.prefix); if (startIdx >= 0) { int endIdx = value.lastIndexOf(ps.suffix); if (endIdx >= 0) { - String spelText = value.substring(startIdx + ps.prefix.length(), endIdx); - int offset = valueExp.getStartPosition() + startIdx + ps.prefix.length() + 1; - return Optional.of(new Snippet(spelText, offset)); + return Optional.of(new EmbeddedLanguageSnippetWithPrefixAndSuffix(embeddedSnippet, startIdx + ps.prefix.length(), endIdx)); } } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelReconciler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelReconciler.java index 9d3db9e29..a4560038b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelReconciler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelReconciler.java @@ -53,7 +53,7 @@ public class JdtSpelReconciler implements JdtAstReconciler { .map(e -> e.getSpelRegion(node)) .filter(o -> o.isPresent()) .map(o -> o.get()) - .forEach(snippet -> spelReconciler.reconcile(snippet.text(), snippet.offset(), problemCollector)); + .forEach(snippet -> spelReconciler.reconcile(snippet.getText(), snippet::toSingleJavaRange, problemCollector)); return super.visit(node); } @@ -63,7 +63,7 @@ public class JdtSpelReconciler implements JdtAstReconciler { .map(e -> e.getSpelRegion(node)) .filter(o -> o.isPresent()) .map(o -> o.get()) - .forEach(snippet -> spelReconciler.reconcile(snippet.text(), snippet.offset(), problemCollector)); + .forEach(snippet -> spelReconciler.reconcile(snippet.getText(), snippet::toSingleJavaRange, problemCollector)); return super.visit(node); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelSemanticTokensProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelSemanticTokensProvider.java index f3077b6e3..10359b83b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelSemanticTokensProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelSemanticTokensProvider.java @@ -60,7 +60,10 @@ public class JdtSpelSemanticTokensProvider implements JdtSemanticTokensProvider .map(e -> e.getSpelRegion(node)) .filter(o -> o.isPresent()) .map(o -> o.get()) - .forEach(snippet -> tokensProvider.computeTokens(snippet.text(), snippet.offset()).forEach(collector::accept)); + .forEach(snippet -> tokensProvider.computeTokens(snippet.getText()).stream() + .flatMap(td -> snippet.toJavaRanges(td.range()).stream().map(r -> new SemanticTokenData(r, + td.type(), td.modifiers()))) + .forEach(collector::accept)); return super.visit(node); } @@ -70,7 +73,10 @@ public class JdtSpelSemanticTokensProvider implements JdtSemanticTokensProvider .map(e -> e.getSpelRegion(node)) .filter(o -> o.isPresent()) .map(o -> o.get()) - .forEach(snippet -> tokensProvider.computeTokens(snippet.text(), snippet.offset()).forEach(collector::accept)); + .forEach(snippet -> tokensProvider.computeTokens(snippet.getText()).stream() + .flatMap(td -> snippet.toJavaRanges(td.range()).stream().map(r -> new SemanticTokenData(r, + td.type(), td.modifiers()))) + .forEach(collector::accept)); return super.visit(node); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/PropertyPlaceHolderSemanticTokens.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/PropertyPlaceHolderSemanticTokens.java index b83a402a2..c0946cefd 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/PropertyPlaceHolderSemanticTokens.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/PropertyPlaceHolderSemanticTokens.java @@ -32,7 +32,7 @@ import org.antlr.v4.runtime.atn.ATNConfigSet; import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.tree.ErrorNode; import org.antlr.v4.runtime.tree.TerminalNode; -import org.springframework.ide.vscode.boot.java.data.jpa.queries.AntlrUtils; +import org.springframework.ide.vscode.boot.java.embadded.lang.AntlrUtils; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensDataProvider; import org.springframework.ide.vscode.parser.placeholder.PropertyPlaceHolderBaseListener; @@ -56,7 +56,7 @@ public class PropertyPlaceHolderSemanticTokens implements SemanticTokensDataProv } @Override - public List computeTokens(String text, int initialOffset) { + public List computeTokens(String text) { PropertyPlaceHolderLexer lexer = new PropertyPlaceHolderLexer(CharStreams.fromString(text)); CommonTokenStream antlrTokens = new CommonTokenStream(lexer); PropertyPlaceHolderParser parser = new PropertyPlaceHolderParser(antlrTokens); @@ -74,7 +74,7 @@ public class PropertyPlaceHolderSemanticTokens implements SemanticTokensDataProv public void exitKey(KeyContext ctx) { // Remove all children nodes semantics as they will be replaced by a single token spanning multiple AST nodes AntlrUtils.getAllLeafs(ctx).forEach(semantics::remove); - int start = ctx.getStart().getStartIndex() + initialOffset; + int start = ctx.getStart().getStartIndex(); int end = start + ctx.getText().length(); tokens.add(new SemanticTokenData(start, end, "property", new String[0])); } @@ -87,7 +87,7 @@ public class PropertyPlaceHolderSemanticTokens implements SemanticTokensDataProv } if (ctx.value() != null) { ValueContext valueCtx = ctx.value(); - int start = valueCtx.getStart().getStartIndex() + initialOffset; + int start = valueCtx.getStart().getStartIndex(); int end = start + valueCtx.getText().length(); tokens.add(new SemanticTokenData(start, end, "string", new String[0])); } @@ -148,8 +148,8 @@ public class PropertyPlaceHolderSemanticTokens implements SemanticTokensDataProv parser.start(); tokens.addAll(semantics.entrySet().stream() - .map(e -> new SemanticTokenData(e.getKey().getStartIndex() + initialOffset, - e.getKey().getStartIndex() + e.getKey().getText().length() + initialOffset, e.getValue(), + .map(e -> new SemanticTokenData(e.getKey().getStartIndex(), + e.getKey().getStartIndex() + e.getKey().getText().length(), e.getValue(), new String[0])) .collect(Collectors.toList())); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelDefinitionProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelDefinitionProvider.java index 33394885e..d36fd036b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelDefinitionProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelDefinitionProvider.java @@ -52,15 +52,17 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex; import org.springframework.ide.vscode.boot.java.Annotations; import org.springframework.ide.vscode.boot.java.IJavaDefinitionProvider; +import org.springframework.ide.vscode.boot.java.embadded.lang.EmbeddedLanguageSnippet; import org.springframework.ide.vscode.boot.java.links.SourceLinks; -import org.springframework.ide.vscode.boot.java.spel.AnnotationParamSpelExtractor.Snippet; import org.springframework.ide.vscode.boot.java.utils.ASTUtils; import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.protocol.spring.Bean; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.text.DocumentRegion; +import org.springframework.ide.vscode.commons.util.text.IRegion; import org.springframework.ide.vscode.commons.util.text.LanguageId; +import org.springframework.ide.vscode.commons.util.text.Region; import org.springframework.ide.vscode.commons.util.text.TextDocument; import org.springframework.ide.vscode.parser.spel.SpelLexer; import org.springframework.ide.vscode.parser.spel.SpelParser; @@ -116,11 +118,11 @@ public class SpelDefinitionProvider implements IJavaDefinitionProvider { return e.getSpelRegion((SingleMemberAnnotation) a); else if (a instanceof NormalAnnotation) return e.getSpelRegion((NormalAnnotation) a); - return Optional.empty(); + return Optional.empty(); }).filter(o -> o.isPresent()).map(o -> o.get()) .filter(snippet -> { - int tokenEndIndex = snippet.offset() + snippet.text().length(); - return snippet.offset() <= (offset) && (offset) <= tokenEndIndex; + IRegion snippetRegion = snippet.getTotalRange(); + return snippetRegion.getStart() <= (offset) && (offset) <= snippetRegion.getEnd(); }).forEach(snippet -> { List beanReferenceTokens = computeTokens(snippet, offset); if (beanReferenceTokens != null && beanReferenceTokens.size() > 0) { @@ -213,8 +215,8 @@ public class SpelDefinitionProvider implements IJavaDefinitionProvider { }).collect(Collectors.toList()); } - private List computeTokens(Snippet snippet, int offset) { - SpelLexer lexer = new SpelLexer(CharStreams.fromString(snippet.text())); + private List computeTokens(EmbeddedLanguageSnippet snippet, int offset) { + SpelLexer lexer = new SpelLexer(CharStreams.fromString(snippet.getText())); CommonTokenStream antlrTokens = new CommonTokenStream(lexer); SpelParser parser = new SpelParser(antlrTokens); @@ -236,8 +238,9 @@ public class SpelDefinitionProvider implements IJavaDefinitionProvider { } private void addTokenData(Token sym, int offset) { - int start = sym.getStartIndex() + snippet.offset(); - int end = sym.getStartIndex() + sym.getText().length() + snippet.offset(); + List symbolRegions = snippet.toJavaRanges(new Region(sym.getStartIndex(), sym.getText().length())); + int start = symbolRegions.get(0).getStart(); + int end = symbolRegions.get(symbolRegions.size() - 1).getEnd(); if (isOffsetWithinToken(start, end, offset)) { beanReferenceTokens.add(new TokenData(sym.getText(), start, end)); } @@ -254,10 +257,10 @@ public class SpelDefinitionProvider implements IJavaDefinitionProvider { return beanReferenceTokens; } - private Optional> parseAndExtractMethodClassPairFromSpel(Snippet snippet, int offset) { + private Optional> parseAndExtractMethodClassPairFromSpel(EmbeddedLanguageSnippet snippet, int offset) { SpelExpressionParser parser = new SpelExpressionParser(); try { - org.springframework.expression.Expression expression = parser.parseExpression(snippet.text()); + org.springframework.expression.Expression expression = parser.parseExpression(snippet.getText()); SpelExpression spelExpressionAST = (SpelExpression) expression; SpelNode rootNode = spelExpressionAST.getAST(); @@ -269,8 +272,8 @@ public class SpelDefinitionProvider implements IJavaDefinitionProvider { } private Optional> extractMethodClassPairFromSpelNodes(SpelNode node, SpelNode parent, - Snippet snippet, int offset) { - if (node instanceof MethodReference && checkOffsetInMethodName(node, snippet.offset(), offset)) { + EmbeddedLanguageSnippet snippet, int offset) { + if (node instanceof MethodReference && checkOffsetInMethodName(node, snippet.toJavaOffset(0), offset)) { MethodReference methodRef = (MethodReference) node; String methodName = methodRef.getName(); String className = extractClassNameFromParent(parent); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelReconciler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelReconciler.java index 8b35334c3..ffa6a929c 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelReconciler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelReconciler.java @@ -10,14 +10,18 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.spel; +import java.util.function.Function; + import org.antlr.v4.runtime.Parser; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.tree.ErrorNode; import org.antlr.v4.runtime.tree.ParseTreeListener; import org.antlr.v4.runtime.tree.TerminalNode; import org.springframework.ide.vscode.boot.java.SpelProblemType; -import org.springframework.ide.vscode.boot.java.data.jpa.queries.AntlrReconciler; +import org.springframework.ide.vscode.boot.java.embadded.lang.AntlrReconciler; import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector; +import org.springframework.ide.vscode.commons.util.text.IRegion; +import org.springframework.ide.vscode.commons.util.text.Region; import org.springframework.ide.vscode.parser.placeholder.PropertyPlaceHolderLexer; import org.springframework.ide.vscode.parser.placeholder.PropertyPlaceHolderParser; import org.springframework.ide.vscode.parser.spel.SpelLexer; @@ -40,25 +44,27 @@ public class SpelReconciler extends AntlrReconciler { } @Override - public void reconcile(String text, int startPosition, IProblemCollector problemCollector) { + public void reconcile(String text, Function mapper, IProblemCollector problemCollector) { if (!enabled) { return; } - super.reconcile(text, startPosition, problemCollector); + super.reconcile(text, mapper, problemCollector); } @Override - protected Parser createParser(String text, int startPosition, IProblemCollector problemCollector) throws Exception { - Parser parser = super.createParser(text, startPosition, problemCollector); + protected Parser createParser(String text, Function mapper, IProblemCollector problemCollector) throws Exception { + Parser parser = super.createParser(text, mapper, problemCollector); // Reconcile embedded SPEL parser.addParseListener(new ParseTreeListener() { private void processTerminal(TerminalNode node) { if (node.getSymbol().getType() == SpelLexer.PROPERTY_PLACE_HOLDER) { - int placeHolderStartPosition = startPosition + node.getSymbol().getStartIndex() + 2; String content = node.getSymbol().getText().substring(2, node.getSymbol().getText().length() - 1); - propertyHolderReconciler.reconcile(content, placeHolderStartPosition, problemCollector); + propertyHolderReconciler.reconcile(content, r -> { + IRegion n = mapper.apply(r); + return new Region(n.getOffset() + node.getSymbol().getStartIndex() + 2, n.getLength()); + }, problemCollector); } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelSemanticTokens.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelSemanticTokens.java index 3beb378be..a0f8243d9 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelSemanticTokens.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/spel/SpelSemanticTokens.java @@ -10,7 +10,66 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.spel; -import static org.springframework.ide.vscode.parser.spel.SpelLexer.*; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.AND; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.ASSIGN; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.BACKTICK; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.BEAN_REF; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.COLON; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.COMMA; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.DEC; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.DIV; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.DOT; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.DOUBLE_QUOTED_STRING; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.ELVIS; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.EQ; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.EQ_KEYWORD; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.FACTORY_BEAN_REF; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.FALSE; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.GE; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.GE_KEYWORD; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.GT; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.GT_KEYWORD; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.HASH; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.IDENTIFIER; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.INC; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.INTEGER_LITERAL; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.LCURLY; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.LE; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.LE_KEYWORD; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.LPAREN; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.LSQUARE; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.LT; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.LT_KEYWORD; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.MATCHES; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.MINUS; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.MOD; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.NE; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.NEW; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.NE_KEYWORD; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.NOT; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.NULL; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.OR; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.PLUS; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.POWER; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.PROJECT; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.PROPERTY_PLACE_HOLDER; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.QMARK; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.RCURLY; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.REAL_LITERAL; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.RPAREN; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.RSQUARE; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.SAFE_NAVI; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.SELECT; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.SELECT_FIRST; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.SELECT_LAST; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.SEMICOLON; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.SINGLE_QUOTED_STRING; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.STAR; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.STRING_LITERAL; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.SYMBOLIC_AND; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.SYMBOLIC_OR; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.T; +import static org.springframework.ide.vscode.parser.spel.SpelLexer.TRUE; import java.util.ArrayList; import java.util.BitSet; @@ -38,6 +97,7 @@ import org.antlr.v4.runtime.tree.ErrorNode; import org.antlr.v4.runtime.tree.TerminalNode; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData; import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensDataProvider; +import org.springframework.ide.vscode.commons.util.text.Region; import org.springframework.ide.vscode.parser.spel.SpelLexer; import org.springframework.ide.vscode.parser.spel.SpelParser; import org.springframework.ide.vscode.parser.spel.SpelParser.BeanReferenceContext; @@ -71,7 +131,7 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider { } @Override - public List computeTokens(String text, int initialOffset) { + public List computeTokens(String text) { SpelLexer lexer = new SpelLexer(CharStreams.fromString(text)); CommonTokenStream antlrTokens = new CommonTokenStream(lexer); SpelParser parser = new SpelParser(antlrTokens); @@ -158,7 +218,7 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider { semantics.put(node.getSymbol(), "string"); break; case PROPERTY_PLACE_HOLDER: - tokens.addAll(computeTokensFromPropertyPlaceHolderNode(node, initialOffset)); + tokens.addAll(computeTokensFromPropertyPlaceHolderNode(node)); break; } } @@ -215,7 +275,7 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider { semantics.remove(ctx.INTEGER_LITERAL().getSymbol()); semantics.remove(ctx.RSQUARE().getSymbol()); - int start = ctx.getStart().getStartIndex() + initialOffset; + int start = ctx.getStart().getStartIndex(); int end = start + ctx.getText().length(); tokens.add(new SemanticTokenData(start, end, "parameter", new String[0])); } @@ -260,8 +320,8 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider { parser.spelExpr(); tokens.addAll(semantics.entrySet().stream() - .map(e -> new SemanticTokenData(e.getKey().getStartIndex() + initialOffset, - e.getKey().getStartIndex() + e.getKey().getText().length() + initialOffset, e.getValue(), + .map(e -> new SemanticTokenData(e.getKey().getStartIndex(), + e.getKey().getStartIndex() + e.getKey().getText().length(), e.getValue(), new String[0])) .collect(Collectors.toList())); @@ -270,18 +330,19 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider { return tokens; } - private Collection computeTokensFromPropertyPlaceHolderNode(TerminalNode node, - int initialOffset) { + private Collection computeTokensFromPropertyPlaceHolderNode(TerminalNode node) { List placeHolderTokens = new ArrayList<>(); - int startPosition = initialOffset + node.getSymbol().getStartIndex(); + int startPosition = node.getSymbol().getStartIndex(); int placeHolderStartPosition = startPosition + 2; int endPosition = startPosition + node.getText().length(); int placeHolderEndPosition = endPosition - 1; // '${' operator placeHolderTokens.add(new SemanticTokenData(startPosition, placeHolderStartPosition, "operator", new String[0])); // Property Place Holder contents - placeHolderTokens.addAll(propertyPlaceHolderSemanticTokens.computeTokens(node.getText().substring(2, node.getText().length() - 1), placeHolderStartPosition)); + propertyPlaceHolderSemanticTokens.computeTokens(node.getText().substring(2, node.getText().length() - 1)) + .stream().map(td -> new SemanticTokenData(new Region(td.range().getOffset() + placeHolderStartPosition, td.range().getLength()), td.type(), td.modifiers())) + .forEach(placeHolderTokens::add); // '}' operator placeHolderTokens.add(new SemanticTokenData(placeHolderEndPosition, endPosition, "operator", new String[0])); return placeHolderTokens; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/XMLElementReconciler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/XMLElementReconciler.java index f2400b2d4..d6ec5793f 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/XMLElementReconciler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/xml/XMLElementReconciler.java @@ -17,6 +17,7 @@ import org.eclipse.lemminx.dom.DOMNode; import org.eclipse.lemminx.dom.DOMRange; import org.springframework.ide.vscode.boot.java.handlers.Reconciler; import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector; +import org.springframework.ide.vscode.commons.util.text.Region; /** * @author mlippert @@ -68,7 +69,7 @@ public class XMLElementReconciler { if (value != null && value.startsWith(prefix) && value.endsWith(postfix)) { String valueToReconcile = value.substring(prefix.length(), value.length() - postfix.length()); - reconciler.reconcile(valueToReconcile, start + prefix.length() + 1, problemCollector); + reconciler.reconcile(valueToReconcile, r -> new Region(r.getOffset() + start + prefix.length() + 1, r.getLength()), problemCollector); } } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/CronReconcilerTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/CronReconcilerTest.java index d682933ce..eb5fb3329 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/CronReconcilerTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/CronReconcilerTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -26,27 +27,27 @@ public class CronReconcilerTest { @Test void noProblems_1() { - reconciler.reconcile("0 0 0 L-3 * *", 0, collector); + reconciler.reconcile("0 0 0 L-3 * *", Function.identity(), collector); assertEquals(0, problems.size()); } @Test void DayOfTheWeekProblems_1() { - reconciler.reconcile("0 0 0 8 * MAR-JUL", 0, collector); + reconciler.reconcile("0 0 0 8 * MAR-JUL", Function.identity(), collector); assertEquals(1, problems.size()); assertReconcileProblem(problems.get(0), CronProblemType.FIELD, 10, 6); } @Test void noProblems_3() { - reconciler.reconcile("MAR-JUL 0 0 8 * *", 0, collector); + reconciler.reconcile("MAR-JUL 0 0 8 * *", Function.identity(), collector); assertEquals(1, problems.size()); assertReconcileProblem(problems.get(0), CronProblemType.FIELD, 0, 7); } @Test void syntax_and_field_problems_1() { - reconciler.reconcile("0 0 0 8LW * MARCH-JUL", 0, collector); + reconciler.reconcile("0 0 0 8LW * MARCH-JUL", Function.identity(), collector); assertEquals(3, problems.size()); assertReconcileProblem(problems.get(0), CronProblemType.SYNTAX, 7, 2); assertReconcileProblem(problems.get(1), CronProblemType.SYNTAX, 12, 5); @@ -55,14 +56,14 @@ public class CronReconcilerTest { @Test void syntax_problems_2() { - reconciler.reconcile("qq#3 0 Blah 1-88LW * JUL-MARCH", 0, collector); + reconciler.reconcile("qq#3 0 Blah 1-88LW * JUL-MARCH", Function.identity(), collector); assertEquals(1, problems.size()); assertReconcileProblem(problems.get(0), CronProblemType.SYNTAX, 0, 2); } @Test void syntax_problems_3() { - reconciler.reconcile("10/2. * * ? * MON-5", 0, collector); + reconciler.reconcile("10/2. * * ? * MON-5", Function.identity(), collector); assertEquals(1, problems.size()); assertReconcileProblem(problems.get(0), CronProblemType.SYNTAX, 4, 0); } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/CronSemanticTokensTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/CronSemanticTokensTest.java index 1b51b5529..11fd168c6 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/CronSemanticTokensTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/CronSemanticTokensTest.java @@ -31,7 +31,7 @@ public class CronSemanticTokensTest { @Test void topHoueEveryDayEveryWeek() { - List tokens = provider.computeTokens("0 0 * * * *", 0); + List tokens = provider.computeTokens("0 0 * * * *"); assertThat(tokens.size()).isEqualTo(6); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); @@ -43,7 +43,7 @@ public class CronSemanticTokensTest { @Test void everyTenSeconds() { - List tokens = provider.computeTokens("*/10 * * * * *", 0); + List tokens = provider.computeTokens("*/10 * * * * *"); assertThat(tokens.size()).isEqualTo(8); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "operator", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(1, 2, "operator", new String[0])); @@ -57,7 +57,7 @@ public class CronSemanticTokensTest { @Test void betweenEightAndTenEveryDay() { - List tokens = provider.computeTokens("0 0 8-10 * * *", 0); + List tokens = provider.computeTokens("0 0 8-10 * * *"); assertThat(tokens.size()).isEqualTo(8); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -71,7 +71,7 @@ public class CronSemanticTokensTest { @Test void everyDayBetweenSixAndSeven() { - List tokens = provider.computeTokens("0 0 6,19 * * *", 0); + List tokens = provider.computeTokens("0 0 6,19 * * *"); assertThat(tokens.size()).isEqualTo(8); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -85,7 +85,7 @@ public class CronSemanticTokensTest { @Test void everyHalfHourBetweenEightAndEleven() { - List tokens = provider.computeTokens("0 0/30 8-10 * * *", 0); + List tokens = provider.computeTokens("0 0/30 8-10 * * *"); assertThat(tokens.size()).isEqualTo(10); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -101,7 +101,7 @@ public class CronSemanticTokensTest { @Test void nineToFiveOnWeekdays() { - List tokens = provider.computeTokens("0 0 9-17 * * MON-FRI", 0); + List tokens = provider.computeTokens("0 0 9-17 * * MON-FRI"); assertThat(tokens.size()).isEqualTo(10); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -117,7 +117,7 @@ public class CronSemanticTokensTest { @Test void christmas() { - List tokens = provider.computeTokens("0 0 0 25 12 ?", 0); + List tokens = provider.computeTokens("0 0 0 25 12 ?"); assertThat(tokens.size()).isEqualTo(6); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -129,7 +129,7 @@ public class CronSemanticTokensTest { @Test void lastDayOfMonthAtMidnight() { - List tokens = provider.computeTokens("0 0 0 L * *", 0); + List tokens = provider.computeTokens("0 0 0 L * *"); assertThat(tokens.size()).isEqualTo(6); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -141,7 +141,7 @@ public class CronSemanticTokensTest { @Test void thirdToLasttDayOfMonthAtMidnight() { - List tokens = provider.computeTokens("0 0 0 L-3 * *", 0); + List tokens = provider.computeTokens("0 0 0 L-3 * *"); assertThat(tokens.size()).isEqualTo(8); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -155,7 +155,7 @@ public class CronSemanticTokensTest { @Test void firstWeekDayOfMonthAtMidnight() { - List tokens = provider.computeTokens("0 0 0 1W * *", 0); + List tokens = provider.computeTokens("0 0 0 1W * *"); assertThat(tokens.size()).isEqualTo(7); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -168,7 +168,7 @@ public class CronSemanticTokensTest { @Test void lastWeekDayOfMonthAtMidnight() { - List tokens = provider.computeTokens("0 0 0 LW * *", 0); + List tokens = provider.computeTokens("0 0 0 LW * *"); assertThat(tokens.size()).isEqualTo(6); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -180,7 +180,7 @@ public class CronSemanticTokensTest { @Test void lastFridayOfMonthAtMidnight() { - List tokens = provider.computeTokens("0 0 0 * * 5L", 0); + List tokens = provider.computeTokens("0 0 0 * * 5L"); assertThat(tokens.size()).isEqualTo(7); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -193,7 +193,7 @@ public class CronSemanticTokensTest { @Test void lastThursdayOfMonthAtMidnight() { - List tokens = provider.computeTokens("0 0 0 * * THUL", 0); + List tokens = provider.computeTokens("0 0 0 * * THUL"); assertThat(tokens.size()).isEqualTo(7); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -206,7 +206,7 @@ public class CronSemanticTokensTest { @Test void secondFridayOfMonthAtMidnight() { - List tokens = provider.computeTokens("0 0 0 ? * 5#2", 0); + List tokens = provider.computeTokens("0 0 0 ? * 5#2"); assertThat(tokens.size()).isEqualTo(8); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -220,7 +220,7 @@ public class CronSemanticTokensTest { @Test void firstMondayOfMonthAtMidnight() { - List tokens = provider.computeTokens("0 0 0 ? * MON#1", 0); + List tokens = provider.computeTokens("0 0 0 ? * MON#1"); assertThat(tokens.size()).isEqualTo(8); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -234,7 +234,7 @@ public class CronSemanticTokensTest { @Test void macro() { - List tokens = provider.computeTokens("@yearly", 0); + List tokens = provider.computeTokens("@yearly"); assertThat(tokens.size()).isEqualTo(1); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 7, "macro", new String[0])); // @yearly } @@ -242,7 +242,7 @@ public class CronSemanticTokensTest { @Test void errors_1() { provider = new CronSemanticTokens(); - List tokens = provider.computeTokens("0 0 0 8LW * Foo#bar", 0); + List tokens = provider.computeTokens("0 0 0 8LW * Foo#bar"); assertThat(tokens.size()).isEqualTo(9); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); // 0 assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "number", new String[0])); // 0 @@ -258,7 +258,7 @@ public class CronSemanticTokensTest { @Test void errors_2() { provider = new CronSemanticTokens(); - List tokens = provider.computeTokens("qq#3 0 Blah 1-88LW * JUL-MARCH", 0); + List tokens = provider.computeTokens("qq#3 0 Blah 1-88LW * JUL-MARCH"); assertThat(tokens.size()).isEqualTo(13); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 2, "enum", new String[0])); // qq assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "operator", new String[0])); // # diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/JdtCronSemanticTokensProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/JdtCronSemanticTokensProviderTest.java index 772cfb8d4..9a2547551 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/JdtCronSemanticTokensProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/cron/JdtCronSemanticTokensProviderTest.java @@ -83,35 +83,35 @@ public class JdtCronSemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(117, 118, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(119, 120, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(121, 122, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(123, 124, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("?"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("?"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(125, 126, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("*"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("*"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(127, 128, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("5"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("5"); token = tokens.get(6); assertThat(token).isEqualTo(new SemanticTokenData(128, 129, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("#"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("#"); token = tokens.get(7); assertThat(token).isEqualTo(new SemanticTokenData(129, 130, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("2"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("2"); } @@ -142,31 +142,31 @@ public class JdtCronSemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(117, 118, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(119, 120, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(121, 122, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(123, 124, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("*"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("*"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(125, 126, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("*"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("*"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(127, 130, "enum", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("THU"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("THU"); token = tokens.get(6); assertThat(token).isEqualTo(new SemanticTokenData(130, 131, "method", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("L"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("L"); } @@ -197,35 +197,35 @@ public class JdtCronSemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(117, 118, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(119, 120, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(121, 122, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(123, 124, "method", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("L"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("L"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(124, 125, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("-"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("-"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(125, 126, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("3"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("3"); token = tokens.get(6); assertThat(token).isEqualTo(new SemanticTokenData(127, 128, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("*"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("*"); token = tokens.get(7); assertThat(token).isEqualTo(new SemanticTokenData(129, 130, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("*"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("*"); } @Test @@ -255,39 +255,39 @@ public class JdtCronSemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(117, 118, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(119, 120, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(121, 122, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(123, 124, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("8"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("8"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(124, 126, "method", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("LW"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("LW"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(127, 128, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("*"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("*"); token = tokens.get(6); assertThat(token).isEqualTo(new SemanticTokenData(129, 132, "enum", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("Foo"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("Foo"); token = tokens.get(7); assertThat(token).isEqualTo(new SemanticTokenData(132, 133, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("#"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("#"); token = tokens.get(8); assertThat(token).isEqualTo(new SemanticTokenData(133, 136, "enum", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("bar"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("bar"); } @Test @@ -317,55 +317,55 @@ public class JdtCronSemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(117, 119, "enum", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("qq"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("qq"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(119, 120, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("#"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("#"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(120, 121, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("3"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("3"); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(122, 123, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("0"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("0"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(124, 128, "enum", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("Blah"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("Blah"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(129, 130, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("1"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("1"); token = tokens.get(6); assertThat(token).isEqualTo(new SemanticTokenData(130, 131, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("-"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("-"); token = tokens.get(7); assertThat(token).isEqualTo(new SemanticTokenData(131, 133, "number", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("88"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("88"); token = tokens.get(8); assertThat(token).isEqualTo(new SemanticTokenData(133, 135, "method", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("LW"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("LW"); token = tokens.get(9); assertThat(token).isEqualTo(new SemanticTokenData(136, 137, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("*"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("*"); token = tokens.get(10); assertThat(token).isEqualTo(new SemanticTokenData(138, 141, "enum", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("JUL"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("JUL"); token = tokens.get(11); assertThat(token).isEqualTo(new SemanticTokenData(141, 142, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("-"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("-"); token = tokens.get(12); assertThat(token).isEqualTo(new SemanticTokenData(142, 147, "enum", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("MARCH"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("MARCH"); } @Test diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/HqlSemanticTokensTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/HqlSemanticTokensTest.java index e68781bcb..61fe2d07a 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/HqlSemanticTokensTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/HqlSemanticTokensTest.java @@ -32,7 +32,7 @@ public class HqlSemanticTokensTest { @Test void simpleQuery_1() { - List tokens = provider.computeTokens("SELECT owner FROM Owner owner", 0); + List tokens = provider.computeTokens("SELECT owner FROM Owner owner"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 12, "variable", new String[0])); assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 17, "keyword", new String[0])); @@ -42,21 +42,9 @@ public class HqlSemanticTokensTest { assertThat(tokens.size()).isEqualTo(5); } - @Test - void initialOffset() { - List tokens = provider.computeTokens("SELECT owner FROM Owner owner", 3); - assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(3, 9, "keyword", new String[0])); - assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(10, 15, "variable", new String[0])); - assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(16, 20, "keyword", new String[0])); - assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(21, 26, "class", new String[0])); - assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(27, 32, "variable", new String[0])); - - assertThat(tokens.size()).isEqualTo(5); - } - @Test void query_with_conflicting_groupby() { - List tokens = provider.computeTokens("SELECT g FROM Group g GROUP BY g.name", 0); + List tokens = provider.computeTokens("SELECT g FROM Group g GROUP BY g.name"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 8, "variable", new String[0])); assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(9, 13, "keyword", new String[0])); @@ -73,7 +61,7 @@ public class HqlSemanticTokensTest { @Test void query_with_parameter() { - List tokens = provider.computeTokens("SELECT DISTINCT owner FROM Owner owner left join owner.pets WHERE owner.lastName LIKE :lastName%", 0); + List tokens = provider.computeTokens("SELECT DISTINCT owner FROM Owner owner left join owner.pets WHERE owner.lastName LIKE :lastName%"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 15, "keyword", new String[0])); // DISTINCT assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(16, 21, "variable", new String[0])); // owner @@ -99,7 +87,7 @@ public class HqlSemanticTokensTest { @Test void query_with_SPEL() { - List tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{id}", 0); + List tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{id}"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 12, "variable", new String[0])); // owner assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 17, "keyword", new String[0])); // FROM @@ -127,7 +115,7 @@ public class HqlSemanticTokensTest { @Test void query_with_SPEL_Tokens() { provider = new HqlSemanticTokens(Optional.of(new SpelSemanticTokens())); - List tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{id}", 0); + List tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{id}"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 12, "variable", new String[0])); // owner assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 17, "keyword", new String[0])); // FROM @@ -155,7 +143,7 @@ public class HqlSemanticTokensTest { @Test void query_with_complex_SPEL_Tokens() { provider = new HqlSemanticTokens(Optional.of(new SpelSemanticTokens())); - List tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{someBean.someProperty != null ? someBean.someProperty : 'default'}", 0); + List tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{someBean.someProperty != null ? someBean.someProperty : 'default'}"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 12, "variable", new String[0])); // owner assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 17, "keyword", new String[0])); // FROM @@ -193,7 +181,7 @@ public class HqlSemanticTokensTest { @Test void instatiotation_1() { provider = new HqlSemanticTokens(Optional.of(new SpelSemanticTokens())); - List tokens = provider.computeTokens("SELECT new com.example.ls.issue.SampleTableSizePojo(t.schemaName, sum(t.tableSize) ) FROM MTables t GROUP BY t.schemaName ORDER BY sum(t.tableSize) DESC", 0); + List tokens = provider.computeTokens("SELECT new com.example.ls.issue.SampleTableSizePojo(t.schemaName, sum(t.tableSize) ) FROM MTables t GROUP BY t.schemaName ORDER BY sum(t.tableSize) DESC"); assertThat(tokens.size()).isEqualTo(32); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQuerySemanticTokensProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQuerySemanticTokensProviderTest.java index a3ee3a53f..8bfaabbc6 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQuerySemanticTokensProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JdtDataQuerySemanticTokensProviderTest.java @@ -78,27 +78,27 @@ public class JdtDataQuerySemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(120, 126, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("SELECT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("SELECT"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(127, 135, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("DISTINCT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("DISTINCT"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(136, 141, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(142, 146, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("FROM"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("FROM"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(147, 152, "class", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("Owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("Owner"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(153, 158, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); } @Test @@ -126,27 +126,27 @@ public class JdtDataQuerySemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(125, 131, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("SELECT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("SELECT"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(132, 140, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("DISTINCT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("DISTINCT"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(141, 146, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(147, 151, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("FROM"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("FROM"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(152, 157, "class", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("Owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("Owner"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(158, 163, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); } @Test @@ -172,27 +172,27 @@ public class JdtDataQuerySemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(128, 134, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("SELECT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("SELECT"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(135, 143, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("DISTINCT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("DISTINCT"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(144, 149, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(150, 154, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("FROM"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("FROM"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(155, 160, "class", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("Owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("Owner"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(161, 166, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); } @Test @@ -219,27 +219,27 @@ public class JdtDataQuerySemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(176, 182, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("SELECT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("SELECT"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(183, 191, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("DISTINCT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("DISTINCT"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(192, 197, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(198, 202, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("FROM"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("FROM"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(203, 208, "class", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("Owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("Owner"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(209, 214, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); } @Test @@ -268,27 +268,27 @@ public class JdtDataQuerySemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(181, 187, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("SELECT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("SELECT"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(188, 196, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("DISTINCT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("DISTINCT"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(197, 202, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(203, 207, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("FROM"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("FROM"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(208, 213, "class", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("Owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("Owner"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(214, 219, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); } @Test @@ -313,47 +313,47 @@ public class JdtDataQuerySemanticTokensProviderTest { List tokens = computeTokens(cu); SemanticTokenData token = tokens.get(0); - assertThat(source.substring(token.start(), token.end())).isEqualTo("SELECT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("SELECT"); assertThat(token).isEqualTo(new SemanticTokenData(128, 134, "keyword", new String[0])); token = tokens.get(1); - assertThat(source.substring(token.start(), token.end())).isEqualTo("*"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("*"); assertThat(token).isEqualTo(new SemanticTokenData(135, 136, "operator", new String[0])); token = tokens.get(2); - assertThat(source.substring(token.start(), token.end())).isEqualTo("FROM"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("FROM"); assertThat(token).isEqualTo(new SemanticTokenData(137, 141, "keyword", new String[0])); token = tokens.get(3); - assertThat(source.substring(token.start(), token.end())).isEqualTo("USERS"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("USERS"); assertThat(token).isEqualTo(new SemanticTokenData(142, 147, "variable", new String[0])); token = tokens.get(4); - assertThat(source.substring(token.start(), token.end())).isEqualTo("u"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("u"); assertThat(token).isEqualTo(new SemanticTokenData(148, 149, "variable", new String[0])); token = tokens.get(5); - assertThat(source.substring(token.start(), token.end())).isEqualTo("WHERE"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("WHERE"); assertThat(token).isEqualTo(new SemanticTokenData(150, 155, "keyword", new String[0])); token = tokens.get(6); - assertThat(source.substring(token.start(), token.end())).isEqualTo("u"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("u"); assertThat(token).isEqualTo(new SemanticTokenData(156, 157, "variable", new String[0])); token = tokens.get(7); - assertThat(source.substring(token.start(), token.end())).isEqualTo("."); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("."); assertThat(token).isEqualTo(new SemanticTokenData(157, 158, "operator", new String[0])); token = tokens.get(8); - assertThat(source.substring(token.start(), token.end())).isEqualTo("status"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("status"); assertThat(token).isEqualTo(new SemanticTokenData(158, 164, "property", new String[0])); token = tokens.get(9); - assertThat(source.substring(token.start(), token.end())).isEqualTo("="); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("="); assertThat(token).isEqualTo(new SemanticTokenData(165, 166, "operator", new String[0])); token = tokens.get(10); - assertThat(source.substring(token.start(), token.end())).isEqualTo("1"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("1"); assertThat(token).isEqualTo(new SemanticTokenData(167, 168, "number", new String[0])); } @@ -380,59 +380,59 @@ public class JdtDataQuerySemanticTokensProviderTest { List tokens = computeTokens(cu); SemanticTokenData token = tokens.get(0); - assertThat(source.substring(token.start(), token.end())).isEqualTo("SELECT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("SELECT"); assertThat(token).isEqualTo(new SemanticTokenData(128, 134, "keyword", new String[0])); token = tokens.get(1); - assertThat(source.substring(token.start(), token.end())).isEqualTo("*"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("*"); assertThat(token).isEqualTo(new SemanticTokenData(135, 136, "operator", new String[0])); token = tokens.get(2); - assertThat(source.substring(token.start(), token.end())).isEqualTo("FROM"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("FROM"); assertThat(token).isEqualTo(new SemanticTokenData(137, 141, "keyword", new String[0])); token = tokens.get(3); - assertThat(source.substring(token.start(), token.end())).isEqualTo("USERS"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("USERS"); assertThat(token).isEqualTo(new SemanticTokenData(142, 147, "variable", new String[0])); token = tokens.get(4); - assertThat(source.substring(token.start(), token.end())).isEqualTo("u"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("u"); assertThat(token).isEqualTo(new SemanticTokenData(148, 149, "variable", new String[0])); token = tokens.get(5); - assertThat(source.substring(token.start(), token.end())).isEqualTo("WHERE"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("WHERE"); assertThat(token).isEqualTo(new SemanticTokenData(150, 155, "keyword", new String[0])); token = tokens.get(6); - assertThat(source.substring(token.start(), token.end())).isEqualTo("u"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("u"); assertThat(token).isEqualTo(new SemanticTokenData(156, 157, "variable", new String[0])); token = tokens.get(7); - assertThat(source.substring(token.start(), token.end())).isEqualTo("."); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("."); assertThat(token).isEqualTo(new SemanticTokenData(157, 158, "operator", new String[0])); token = tokens.get(8); - assertThat(source.substring(token.start(), token.end())).isEqualTo("status"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("status"); assertThat(token).isEqualTo(new SemanticTokenData(158, 164, "property", new String[0])); token = tokens.get(9); - assertThat(source.substring(token.start(), token.end())).isEqualTo("="); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("="); assertThat(token).isEqualTo(new SemanticTokenData(165, 166, "operator", new String[0])); token = tokens.get(10); - assertThat(source.substring(token.start(), token.end())).isEqualTo("?"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("?"); assertThat(token).isEqualTo(new SemanticTokenData(167, 168, "operator", new String[0])); token = tokens.get(11); - assertThat(source.substring(token.start(), token.end())).isEqualTo("#{"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("#{"); assertThat(token).isEqualTo(new SemanticTokenData(168, 170, "operator", new String[0])); token = tokens.get(12); - assertThat(source.substring(token.start(), token.end())).isEqualTo("status"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("status"); assertThat(token).isEqualTo(new SemanticTokenData(170, 176, "variable", new String[0])); token = tokens.get(13); - assertThat(source.substring(token.start(), token.end())).isEqualTo("}"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("}"); assertThat(token).isEqualTo(new SemanticTokenData(176, 177, "operator", new String[0])); } @@ -457,27 +457,84 @@ public class JdtDataQuerySemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(101, 107, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("SELECT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("SELECT"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(108, 116, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("DISTINCT"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("DISTINCT"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(117, 122, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(123, 127, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("FROM"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("FROM"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(128, 133, "class", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("Owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("Owner"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(134, 139, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("owner"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("owner"); + } + + @Test + void nativeConcatenatedStringQuery() throws Exception { + String source = """ + package my.package + + import org.springframework.data.jpa.repository.Query; + + public interface OwnerRepository { + + @Query(value = "SELECT" + + " DIS" + + "TINCT" + + " test FROM Te" + + "st", nativeQuery = true) + void findByLastName(); + } + """; + + String uri = Paths.get(jp.getLocationUri()).resolve("src/main/resource/my/package/OwnerRepository.java").toUri() + .toASCIIString(); + CompilationUnit cu = CompilationUnitCache.parse2(source.toCharArray(), uri, "OwnerRepository.java", jp); + + assertThat(cu).isNotNull(); + + List tokens = computeTokens(cu); + + SemanticTokenData token = tokens.get(0); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("SELECT"); + assertThat(token).isEqualTo(new SemanticTokenData(128, 134, "keyword", new String[0])); + + token = tokens.get(1); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("DIS"); + assertThat(token).isEqualTo(new SemanticTokenData(142, 145, "keyword", new String[0])); + + token = tokens.get(2); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("TINCT"); + assertThat(token).isEqualTo(new SemanticTokenData(152, 157, "keyword", new String[0])); + + token = tokens.get(3); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("test"); + assertThat(token).isEqualTo(new SemanticTokenData(165, 169, "variable", new String[0])); + + token = tokens.get(4); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("FROM"); + assertThat(token).isEqualTo(new SemanticTokenData(170, 174, "keyword", new String[0])); + + token = tokens.get(5); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("Te"); + assertThat(token).isEqualTo(new SemanticTokenData(175, 177, "variable", new String[0])); + + token = tokens.get(6); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("st"); + assertThat(token).isEqualTo(new SemanticTokenData(184, 186, "variable", new String[0])); + } + } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JpqlSemanticTokensTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JpqlSemanticTokensTest.java index f432191c2..87ad3a6ac 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JpqlSemanticTokensTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/JpqlSemanticTokensTest.java @@ -32,7 +32,7 @@ public class JpqlSemanticTokensTest { @Test void simpleQuery_1() { - List tokens = provider.computeTokens("SELECT owner FROM Owner owner", 0); + List tokens = provider.computeTokens("SELECT owner FROM Owner owner"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 12, "variable", new String[0])); assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 17, "keyword", new String[0])); @@ -42,21 +42,9 @@ public class JpqlSemanticTokensTest { assertThat(tokens.size()).isEqualTo(5); } - @Test - void initialOffset() { - List tokens = provider.computeTokens("SELECT owner FROM Owner owner", 3); - assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(3, 9, "keyword", new String[0])); - assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(10, 15, "variable", new String[0])); - assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(16, 20, "keyword", new String[0])); - assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(21, 26, "class", new String[0])); - assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(27, 32, "variable", new String[0])); - - assertThat(tokens.size()).isEqualTo(5); - } - @Test void query_with_conflicting_groupby() { - List tokens = provider.computeTokens("SELECT g FROM G g GROUP BY g.name", 0); + List tokens = provider.computeTokens("SELECT g FROM G g GROUP BY g.name"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 8, "variable", new String[0])); // g assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(9, 13, "keyword", new String[0])); // FROM @@ -73,7 +61,7 @@ public class JpqlSemanticTokensTest { @Test void query_with_parameter() { - List tokens = provider.computeTokens("SELECT f from Student f LEFT JOIN f.classTbls s WHERE s.ClassName = :className", 0); + List tokens = provider.computeTokens("SELECT f from Student f LEFT JOIN f.classTbls s WHERE s.ClassName = :className"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 8, "variable", new String[0])); // f @@ -99,7 +87,7 @@ public class JpqlSemanticTokensTest { @Test void query_with_SPEL() { - List tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{id}", 0); + List tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{id}"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 12, "variable", new String[0])); // owner assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 17, "keyword", new String[0])); // FROM @@ -127,7 +115,7 @@ public class JpqlSemanticTokensTest { @Test void query_with_SPEL_Tokens() { provider = new JpqlSemanticTokens(Optional.of(new SpelSemanticTokens())); - List tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{id}", 0); + List tokens = provider.computeTokens("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:#{id}"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 12, "variable", new String[0])); // owner assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 17, "keyword", new String[0])); // FROM diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/MySqlSemanticTokensTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/MySqlSemanticTokensTest.java index c53a0f18e..6c8bc5f4f 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/MySqlSemanticTokensTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/MySqlSemanticTokensTest.java @@ -32,7 +32,7 @@ public class MySqlSemanticTokensTest { @Test void simple() { - List tokens = provider.computeTokens("SELECT * from Document document WHERE document.id=fn_module_candidates()", 0); + List tokens = provider.computeTokens("SELECT * from Document document WHERE document.id=fn_module_candidates()"); assertThat(tokens.size()).isEqualTo(13); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 8, "operator", new String[0])); @@ -52,7 +52,7 @@ public class MySqlSemanticTokensTest { @Test void parametersInQuery() { - List tokens = provider.computeTokens("DELETE FROM component_document WHERE item_document_id = :itemDocumentId", 0); + List tokens = provider.computeTokens("DELETE FROM component_document WHERE item_document_id = :itemDocumentId"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 11, "keyword", new String[0])); assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(12, 30, "variable", new String[0])); @@ -67,7 +67,7 @@ public class MySqlSemanticTokensTest { @Test void spelInQuery() { - List tokens = provider.computeTokens("DELETE FROM component_document WHERE item_document_id = :#{someBean}", 0); + List tokens = provider.computeTokens("DELETE FROM component_document WHERE item_document_id = :#{someBean}"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 11, "keyword", new String[0])); assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(12, 30, "variable", new String[0])); @@ -84,7 +84,7 @@ public class MySqlSemanticTokensTest { @Test void complexSpelInQuery() { - List tokens = provider.computeTokens("DELETE FROM component_document WHERE item_document_id = :#{someBean.someProperty != null ? someBean.someProperty : 'default'}", 0); + List tokens = provider.computeTokens("DELETE FROM component_document WHERE item_document_id = :#{someBean.someProperty != null ? someBean.someProperty : 'default'}"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 11, "keyword", new String[0])); assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(12, 30, "variable", new String[0])); diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokensTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokensTest.java index 1f356b669..bd81a6497 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokensTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/jpa/queries/PostgreSqlSemanticTokensTest.java @@ -32,7 +32,7 @@ public class PostgreSqlSemanticTokensTest { @Test void simple() { - List tokens = provider.computeTokens("SELECT * from fn_module_candidates", 0); + List tokens = provider.computeTokens("SELECT * from fn_module_candidates"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 8, "operator", new String[0])); assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(9, 13, "keyword", new String[0])); @@ -51,7 +51,7 @@ public class PostgreSqlSemanticTokensTest { WHERE document.project_id=?1 AND json_path_exists(document.content::jsonb, ('strict $.content.**.id ? (@ == "\\' || representation.targetobjectid || \\'")')::jsonpath) ) - """, 0); + """); assertThat(tokens.size()).isEqualTo(43); assertThat(tokens.get(10)).isEqualTo(new SemanticTokenData(74, 75, "parameter", new String[0])); // 1 from ?1 @@ -66,7 +66,7 @@ public class PostgreSqlSemanticTokensTest { @Test void spelInQuery() { - List tokens = provider.computeTokens("DELETE FROM component_document WHERE item_document_id = :#{someBean}", 0); + List tokens = provider.computeTokens("DELETE FROM component_document WHERE item_document_id = :#{someBean}"); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 11, "keyword", new String[0])); assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(12, 30, "variable", new String[0])); @@ -83,7 +83,7 @@ public class PostgreSqlSemanticTokensTest { @Test void semiColonAtEnd() { - List tokens = provider.computeTokens(" select count(*) from anecdote where anecdote_id=:anecdote ; ", 0); + List tokens = provider.computeTokens(" select count(*) from anecdote where anecdote_id=:anecdote ; "); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(1, 7, "keyword", new String[0])); // select assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(8, 13, "method", new String[0])); // count assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 14, "operator", new String[0])); // ( @@ -103,7 +103,7 @@ public class PostgreSqlSemanticTokensTest { @Test void parameterInLimitClause_1() { - List tokens = provider.computeTokens("SELECT * FROM cards ORDER BY random() LIMIT ?2", 0); + List tokens = provider.computeTokens("SELECT * FROM cards ORDER BY random() LIMIT ?2"); assertThat(tokens.size()).isEqualTo(12); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); @@ -122,7 +122,7 @@ public class PostgreSqlSemanticTokensTest { @Test void parameterInLimitClause_2() { - List tokens = provider.computeTokens("SELECT * FROM cards ORDER BY random() LIMIT ?2", 0); + List tokens = provider.computeTokens("SELECT * FROM cards ORDER BY random() LIMIT ?2"); assertThat(tokens.size()).isEqualTo(12); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); @@ -141,7 +141,7 @@ public class PostgreSqlSemanticTokensTest { @Test void parameterInLimitClause_3() { - List tokens = provider.computeTokens("SELECT * FROM cards ORDER BY random() LIMIT :#{qq}", 0); + List tokens = provider.computeTokens("SELECT * FROM cards ORDER BY random() LIMIT :#{qq}"); assertThat(tokens.size()).isEqualTo(14); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); @@ -162,7 +162,7 @@ public class PostgreSqlSemanticTokensTest { @Test void parameterInLimitClause_4() { - List tokens = provider.computeTokens("SELECT * FROM cards ORDER BY random() LIMIT :limit", 0); + List tokens = provider.computeTokens("SELECT * FROM cards ORDER BY random() LIMIT :limit"); assertThat(tokens.size()).isEqualTo(12); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); @@ -181,19 +181,19 @@ public class PostgreSqlSemanticTokensTest { @Test void notInInsideWhereClausePredicate() { - List tokens = provider.computeTokens("delete from SAMPLE_TABLE where id not in (select top 1 id from SAMPLE_TABLE order by TABLE_NAME desc)", 0); + List tokens = provider.computeTokens("delete from SAMPLE_TABLE where id not in (select top 1 id from SAMPLE_TABLE order by TABLE_NAME desc)"); assertThat(tokens.size()).isEqualTo(19); } @Test void keywordAsIdentifier() { - List tokens = provider.computeTokens("SELECT SCHEMA_NAME, TABLE_NAME, VERSION from SAMPLE_TABLE", 0); + List tokens = provider.computeTokens("SELECT SCHEMA_NAME, TABLE_NAME, VERSION from SAMPLE_TABLE"); assertThat(tokens.size()).isEqualTo(8); } @Test void topInSelectClause() { - List tokens = provider.computeTokens("select top 1 * from SAMPLE_TABLE where SCHEMA_NAME = ?1", 0); + List tokens = provider.computeTokens("select top 1 * from SAMPLE_TABLE where SCHEMA_NAME = ?1"); assertThat(tokens.size()).isEqualTo(11); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); @@ -212,7 +212,7 @@ public class PostgreSqlSemanticTokensTest { @Test void over_clause_1() { List tokens = provider.computeTokens("SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) FROM empsalary;\n" - + "", 0); + + ""); assertThat(tokens.size()).isEqualTo(20); } @@ -222,21 +222,21 @@ public class PostgreSqlSemanticTokensTest { SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY salary DESC) FROM empsalary; - """, 0); + """); assertThat(tokens.size()).isEqualTo(23); } @Test void over_clause_3() { List tokens = provider.computeTokens("SELECT salary, sum(salary) OVER () FROM empsalary;" - + "", 0); + + ""); assertThat(tokens.size()).isEqualTo(13); } @Test void over_clause_4() { List tokens = provider.computeTokens("SELECT salary, sum(salary) OVER (ORDER BY salary) FROM empsalary;" - + "", 0); + + ""); assertThat(tokens.size()).isEqualTo(16); } @@ -250,7 +250,7 @@ public class PostgreSqlSemanticTokensTest { FROM empsalary ) AS ss WHERE pos < 3; - """, 0); + """); assertThat(tokens.size()).isEqualTo(46); } @@ -260,7 +260,7 @@ public class PostgreSqlSemanticTokensTest { SELECT sum(salary) OVER w, avg(salary) OVER w FROM empsalary WINDOW w AS (PARTITION BY depname ORDER BY salary DESC); - """, 0); + """); assertThat(tokens.size()).isEqualTo(29); } @@ -282,7 +282,7 @@ public class PostgreSqlSemanticTokensTest { (rn = 1 OR status = 10) AND (scenario = 11 OR scenario = 8) ORDER BY status DESC - """, 0); + """); assertThat(tokens.size()).isEqualTo(74); } @@ -290,7 +290,7 @@ public class PostgreSqlSemanticTokensTest { void collate_1() { List tokens = provider.computeTokens(""" SELECT DISTINCT test COLLATE "numeric" FROM Test - """, 0); + """); assertThat(tokens.size()).isEqualTo(7); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 15, "keyword", new String[0])); // DISTICT @@ -303,9 +303,24 @@ public class PostgreSqlSemanticTokensTest { @Test void collate_2() { + List tokens = provider.computeTokens(""" + SELECT DISTINCT test COLLATE \"numeric\" FROM Test + """); + assertThat(tokens.size()).isEqualTo(7); + assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT + assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 15, "keyword", new String[0])); // DISTICT + assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(16, 20, "variable", new String[0])); // test + assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(21, 28, "keyword", new String[0])); // COLLATE + assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(29, 38, "variable", new String[0])); // \"numeric\" + assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(39, 43, "keyword", new String[0])); // FROM + assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(44, 48, "variable", new String[0])); // Test + } + + @Test + void collate_3() { List tokens = provider.computeTokens(""" SELECT a COLLATE "de_DE" < b FROM test1 - """, 0); + """); assertThat(tokens.size()).isEqualTo(8); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "keyword", new String[0])); // SELECT assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 8, "variable", new String[0])); // a diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelSemanticTokensProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelSemanticTokensProviderTest.java index 787e7ce55..c2c3c73d1 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelSemanticTokensProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/JdtSpelSemanticTokensProviderTest.java @@ -81,39 +81,39 @@ public class JdtSpelSemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(119, 122, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("new"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("new"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(123, 129, "method", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("String"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("String"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(129, 130, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("("); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("("); token = tokens.get(3); assertThat(token).isEqualTo(new SemanticTokenData(130, 143, "string", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("'hello world'"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("'hello world'"); token = tokens.get(4); assertThat(token).isEqualTo(new SemanticTokenData(143, 144, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo(")"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo(")"); token = tokens.get(5); assertThat(token).isEqualTo(new SemanticTokenData(144, 145, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("."); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("."); token = tokens.get(6); assertThat(token).isEqualTo(new SemanticTokenData(145, 156, "method", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("toUpperCase"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("toUpperCase"); token = tokens.get(7); assertThat(token).isEqualTo(new SemanticTokenData(156, 157, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("("); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("("); token = tokens.get(8); assertThat(token).isEqualTo(new SemanticTokenData(157, 158, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo(")"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo(")"); } @@ -142,16 +142,16 @@ public class JdtSpelSemanticTokensProviderTest { assertThat(tokens.size()).isEqualTo(3); SemanticTokenData token = tokens.get(0); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("'invalid alphabetic string #$1'"); assertThat(token).isEqualTo(new SemanticTokenData(113, 144, "string", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("'invalid alphabetic string #$1'"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(145, 152, "keyword", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("matches"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("matches"); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(153, 166, "string", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("'[a-zA-Z\\s]+'"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("'[a-zA-Z\\s]+'"); } @@ -182,15 +182,108 @@ public class JdtSpelSemanticTokensProviderTest { SemanticTokenData token = tokens.get(0); assertThat(token).isEqualTo(new SemanticTokenData(121, 125, "variable", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("demo"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("demo"); token = tokens.get(1); assertThat(token).isEqualTo(new SemanticTokenData(125, 126, "operator", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("."); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("."); token = tokens.get(2); assertThat(token).isEqualTo(new SemanticTokenData(126, 130, "property", new String[0])); - assertThat(source.substring(token.start(), token.end())).isEqualTo("cron"); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("cron"); + } + + @Test + void concatenatedString() throws Exception { + String source = """ + package my.package + + import org.springframework.beans.factory.annotation.Value; + + public class Owner { + + @Value("#{'inval" + "id alphabetic s" + "tring #$1' mat" + "ches '[a-z" + "A-Z\\s]+' }") + String s; + + } + """; + + String uri = Paths.get(jp.getLocationUri()).resolve("src/main/resource/my/package/OwnerRepository.java").toUri().toASCIIString(); + CompilationUnit cu = CompilationUnitCache.parse2(source.toCharArray(), uri, "OwnerRepository.java", jp); + + assertThat(cu).isNotNull(); + + List tokens = computeTokens(cu); + + assertThat(tokens.size()).isEqualTo(7); + //id alphabetic string #$1' + SemanticTokenData token = tokens.get(0); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("'inval"); + assertThat(token).isEqualTo(new SemanticTokenData(113, 119, "string", new String[0])); + + token = tokens.get(1); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("id alphabetic s"); + assertThat(token).isEqualTo(new SemanticTokenData(124, 139, "string", new String[0])); + + token = tokens.get(2); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("tring #$1'"); + assertThat(token).isEqualTo(new SemanticTokenData(144, 154, "string", new String[0])); + + token = tokens.get(3); + assertThat(token).isEqualTo(new SemanticTokenData(155, 158, "keyword", new String[0])); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("mat"); + + token = tokens.get(4); + assertThat(token).isEqualTo(new SemanticTokenData(163, 167, "keyword", new String[0])); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("ches"); + + token = tokens.get(5); + assertThat(token).isEqualTo(new SemanticTokenData(168, 173, "string", new String[0])); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("'[a-z"); + + token = tokens.get(6); + assertThat(token).isEqualTo(new SemanticTokenData(178, 186, "string", new String[0])); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("A-Z\\s]+'"); + } + + @Test + void textBlock() throws Exception { + String source = """ + package my.package + + import org.springframework.beans.factory.annotation.Value; + + public class Owner { + + @Value(\""" + #{'invalid alphabetic string #$1' matches '[a-zA-Z\\s]+' } + \""") + String s; + + } + """; + + String uri = Paths.get(jp.getLocationUri()).resolve("src/main/resource/my/package/OwnerRepository.java").toUri().toASCIIString(); + CompilationUnit cu = CompilationUnitCache.parse2(source.toCharArray(), uri, "OwnerRepository.java", jp); + + assertThat(cu).isNotNull(); + + List tokens = computeTokens(cu); + + assertThat(tokens.size()).isEqualTo(3); + + SemanticTokenData token = tokens.get(0); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("'invalid alphabetic string #$1'"); + assertThat(token).isEqualTo(new SemanticTokenData(118, 149, "string", new String[0])); + + token = tokens.get(1); + assertThat(token).isEqualTo(new SemanticTokenData(150, 157, "keyword", new String[0])); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("matches"); + + token = tokens.get(2); + assertThat(token).isEqualTo(new SemanticTokenData(158, 171, "string", new String[0])); + assertThat(source.substring(token.getStart(), token.getEnd())).isEqualTo("'[a-zA-Z\\s]+'"); + } } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/PropertyPlaceHolderSemanticTokensTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/PropertyPlaceHolderSemanticTokensTest.java index 70d018d78..f3c5cb629 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/PropertyPlaceHolderSemanticTokensTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/PropertyPlaceHolderSemanticTokensTest.java @@ -15,7 +15,7 @@ public class PropertyPlaceHolderSemanticTokensTest { @Test void propertyWithDefault() { - List tokens = provider.computeTokens("server.port:5673", 0); + List tokens = provider.computeTokens("server.port:5673"); assertThat(tokens.size()).isEqualTo(3); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 11, "property", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(11, 12, "operator", new String[0])); @@ -24,14 +24,14 @@ public class PropertyPlaceHolderSemanticTokensTest { @Test void propertyOnly() { - List tokens = provider.computeTokens("server.port", 0); + List tokens = provider.computeTokens("server.port"); assertThat(tokens.size()).isEqualTo(1); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 11, "property", new String[0])); } @Test void propertyWithEmptyDefaulValue() { - List tokens = provider.computeTokens("server.port:", 0); + List tokens = provider.computeTokens("server.port:"); assertThat(tokens.size()).isEqualTo(3); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 11, "property", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(11, 12, "operator", new String[0])); @@ -41,7 +41,7 @@ public class PropertyPlaceHolderSemanticTokensTest { @Test void error_1() { provider = new PropertyPlaceHolderSemanticTokens(Optional.empty()); - List tokens = provider.computeTokens("server.:", 0); + List tokens = provider.computeTokens("server.:"); assertThat(tokens.size()).isEqualTo(3); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "property", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(6, 7, "property", new String[0])); @@ -51,7 +51,7 @@ public class PropertyPlaceHolderSemanticTokensTest { @Test void error_2() { provider = new PropertyPlaceHolderSemanticTokens(Optional.empty()); - List tokens = provider.computeTokens("server.", 0); + List tokens = provider.computeTokens("server."); assertThat(tokens.size()).isEqualTo(2); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 6, "property", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(6, 7, "property", new String[0])); diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/SpelSemanticTokensTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/SpelSemanticTokensTest.java index 2f2410c04..a28ab70f4 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/SpelSemanticTokensTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/spel/SpelSemanticTokensTest.java @@ -25,7 +25,7 @@ public class SpelSemanticTokensTest { @Test void simpleCompare() { - List tokens = provider.computeTokens("1 >= 1", 0); + List tokens = provider.computeTokens("1 >= 1"); assertThat(tokens.size()).isEqualTo(3); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 4, "operator", new String[0])); @@ -34,7 +34,7 @@ public class SpelSemanticTokensTest { @Test void simpleCompareWithOp() { - List tokens = provider.computeTokens("1 ge 1", 0); + List tokens = provider.computeTokens("1 ge 1"); assertThat(tokens.size()).isEqualTo(3); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 4, "keyword", new String[0])); @@ -43,7 +43,7 @@ public class SpelSemanticTokensTest { @Test void logicalOperators() { - List tokens = provider.computeTokens("4 > 3 or 15 < 10", 0); + List tokens = provider.computeTokens("4 > 3 or 15 < 10"); assertThat(tokens.size()).isEqualTo(7); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "number", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 3, "operator", new String[0])); @@ -56,7 +56,7 @@ public class SpelSemanticTokensTest { @Test void conditionalOperators() { - List tokens = provider.computeTokens("someBean.someProperty != null ? someBean.someProperty : 'default'", 0); + List tokens = provider.computeTokens("someBean.someProperty != null ? someBean.someProperty : 'default'"); assertThat(tokens.size()).isEqualTo(11); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 8, "variable", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(8, 9, "operator", new String[0])); @@ -73,7 +73,7 @@ public class SpelSemanticTokensTest { @Test void regex() { - List tokens = provider.computeTokens("'invalid alphabetic string #$1' matches '[a-zA-Z\\s]+' ", 0); + List tokens = provider.computeTokens("'invalid alphabetic string #$1' matches '[a-zA-Z\\s]+' "); assertThat(tokens.size()).isEqualTo(3); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 31, "string", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(32, 39, "keyword", new String[0])); @@ -82,7 +82,7 @@ public class SpelSemanticTokensTest { @Test void accessMapObj() { - List tokens = provider.computeTokens("carPark.carsByDriver['Driver1']", 0); + List tokens = provider.computeTokens("carPark.carsByDriver['Driver1']"); assertThat(tokens.size()).isEqualTo(6); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 7, "variable", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 8, "operator", new String[0])); @@ -94,7 +94,7 @@ public class SpelSemanticTokensTest { @Test void accessListItems() { - List tokens = provider.computeTokens("carPark.cars[0]", 0); + List tokens = provider.computeTokens("carPark.cars[0]"); assertThat(tokens.size()).isEqualTo(6); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 7, "variable", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(7, 8, "operator", new String[0])); @@ -106,7 +106,7 @@ public class SpelSemanticTokensTest { @Test void beanReference() { - List tokens = provider.computeTokens("@vetRepo", 0); + List tokens = provider.computeTokens("@vetRepo"); assertThat(tokens.size()).isEqualTo(2); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 1, "operator", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(1, 8, "type", new String[0])); @@ -114,7 +114,7 @@ public class SpelSemanticTokensTest { @Test void contructorAndMethod() { - List tokens = provider.computeTokens("new String('hello world').toUpperCase()", 0); + List tokens = provider.computeTokens("new String('hello world').toUpperCase()"); assertThat(tokens.size()).isEqualTo(9); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 3, "keyword", new String[0])); assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(4, 10, "method", new String[0])); @@ -130,7 +130,7 @@ public class SpelSemanticTokensTest { //https://github.com/spring-projects/sts4/issues/1320 @Test void inputParameter() { - List tokens = provider.computeTokens("[1].size().longValue()", 0); + List tokens = provider.computeTokens("[1].size().longValue()"); assertThat(tokens.size()).isEqualTo(9); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 3, "parameter", new String[0])); // [1] assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(3, 4, "operator", new String[0])); // . @@ -145,7 +145,7 @@ public class SpelSemanticTokensTest { @Test void withPropertyPlaceHolder() { - List tokens = provider.computeTokens("${server.port:8080} == 8080", 0); + List tokens = provider.computeTokens("${server.port:8080} == 8080"); assertThat(tokens.size()).isEqualTo(7); assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 2, "operator", new String[0])); // ${ assertThat(tokens.get(1)).isEqualTo(new SemanticTokenData(2, 13, "property", new String[0])); // server.port