Property place holder support inside SPEL

This commit is contained in:
aboyko
2024-09-10 22:00:20 -04:00
parent 30abaec4d6
commit fca3fc0566
24 changed files with 2391 additions and 831 deletions

View File

@@ -12,4 +12,5 @@ java -jar ${workdir}/antlr-${ANTLR_VERSION}.jar MySqlLexer.g4 MySqlParser.g4 -o
java -jar ${workdir}/antlr-${ANTLR_VERSION}.jar SpelLexer.g4 SpelParser.g4 -o ${workdir}/src/main/java/org/springframework/ide/vscode/parser/spel -package org.springframework.ide.vscode.parser.spel
java -jar ${workdir}/antlr-${ANTLR_VERSION}.jar PostgreSqlLexer.g4 PostgreSqlParser.g4 -o ${workdir}/src/main/java/org/springframework/ide/vscode/parser/postgresql -package org.springframework.ide.vscode.parser.postgresql
java -jar ${workdir}/antlr-${ANTLR_VERSION}.jar CronLexer.g4 CronParser.g4 -o ${workdir}/src/main/java/org/springframework/ide/vscode/parser/cron -package org.springframework.ide.vscode.parser.cron
java -jar ${workdir}/antlr-${ANTLR_VERSION}.jar PropertyPlaceHolder.g4 -o ${workdir}/src/main/java/org/springframework/ide/vscode/parser/placeholder -package org.springframework.ide.vscode.parser.placeholder

View File

@@ -0,0 +1,74 @@
/*******************************************************************************
* 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
*******************************************************************************/
/**
* Based on the answer to this Stack Overflow question:
* https://stackoverflow.com/questions/6132529/antlr-parsing-java-properties
*/
grammar PropertyPlaceHolder;
start
: line* EOF
;
line
: Space* keyDefaultValuePair Space* EOF
;
keyDefaultValuePair
: key
| key defaultValue
;
defaultValue
: Colon value
;
key
: identifier (Dot identifier)*
;
identifier
: Identifier+
;
value
: (Identifier | Exclamation | Number | Space | Backslash Backslash | Backslash LineBreak | Equals | Colon | Dot)*
;
Backslash : '\\';
Colon : ':';
Equals : '=';
Exclamation: '!';
Number : '#';
Dot : '.';
LineBreak
: '\r'? '\n'
| '\r'
;
Space
: ' '
| '\t'
| '\f'
| LineBreak
;
Identifier
: IdentifierChar+
;
fragment IdentifierChar
: ~(' ' | ':' | '=' | '\r' | '\n' | '.')
| Backslash (Colon | Equals)
;

View File

@@ -141,6 +141,10 @@ DOUBLE_QUOTED_STRING
: '"' ( '""' | ~["\n] )* '"'
;
PROPERTY_PLACE_HOLDER
: '${' (.)*? '}'
;
fragment INTEGER_TYPE_SUFFIX : ( 'L' | 'l' );
fragment HEX_DIGIT : [0-9A-Fa-f];
fragment DECIMAL_DIGIT: [0-9];
@@ -184,4 +188,4 @@ TEMPLATE_TEXT
BACKTICK_IN_TEMPLATE
: '`' -> type(BACKTICK), popMode
;
;

View File

@@ -59,6 +59,7 @@ node
nonDottedNode
: (LSQUARE spelExpr RSQUARE)
| inputParameter
| propertyPlaceHolder
;
dottedNode
@@ -107,6 +108,7 @@ startNode
| selection
| inlineListOrMap
| inputParameter
| propertyPlaceHolder
;
@@ -178,3 +180,7 @@ inputParameter
: (LSQUARE INTEGER_LITERAL RSQUARE)
;
propertyPlaceHolder
: PROPERTY_PLACE_HOLDER
;

View File

@@ -0,0 +1,124 @@
// Generated from PropertyPlaceHolder.g4 by ANTLR 4.13.1
package org.springframework.ide.vscode.parser.placeholder;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.TerminalNode;
/**
* This class provides an empty implementation of {@link PropertyPlaceHolderListener},
* which can be extended to create a listener which only needs to handle a subset
* of the available methods.
*/
@SuppressWarnings("CheckReturnValue")
public class PropertyPlaceHolderBaseListener implements PropertyPlaceHolderListener {
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterStart(PropertyPlaceHolderParser.StartContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitStart(PropertyPlaceHolderParser.StartContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterLine(PropertyPlaceHolderParser.LineContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitLine(PropertyPlaceHolderParser.LineContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterKeyDefaultValuePair(PropertyPlaceHolderParser.KeyDefaultValuePairContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitKeyDefaultValuePair(PropertyPlaceHolderParser.KeyDefaultValuePairContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterDefaultValue(PropertyPlaceHolderParser.DefaultValueContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitDefaultValue(PropertyPlaceHolderParser.DefaultValueContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterKey(PropertyPlaceHolderParser.KeyContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitKey(PropertyPlaceHolderParser.KeyContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterIdentifier(PropertyPlaceHolderParser.IdentifierContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitIdentifier(PropertyPlaceHolderParser.IdentifierContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterValue(PropertyPlaceHolderParser.ValueContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitValue(PropertyPlaceHolderParser.ValueContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterEveryRule(ParserRuleContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitEveryRule(ParserRuleContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void visitTerminal(TerminalNode node) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void visitErrorNode(ErrorNode node) { }
}

View File

@@ -0,0 +1,154 @@
// Generated from PropertyPlaceHolder.g4 by ANTLR 4.13.1
package org.springframework.ide.vscode.parser.placeholder;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue", "this-escape"})
public class PropertyPlaceHolderLexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
public static final int
Backslash=1, Colon=2, Equals=3, Exclamation=4, Number=5, Dot=6, LineBreak=7,
Space=8, Identifier=9;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
public static String[] modeNames = {
"DEFAULT_MODE"
};
private static String[] makeRuleNames() {
return new String[] {
"Backslash", "Colon", "Equals", "Exclamation", "Number", "Dot", "LineBreak",
"Space", "Identifier", "IdentifierChar"
};
}
public static final String[] ruleNames = makeRuleNames();
private static String[] makeLiteralNames() {
return new String[] {
null, "'\\'", "':'", "'='", "'!'", "'#'", "'.'"
};
}
private static final String[] _LITERAL_NAMES = makeLiteralNames();
private static String[] makeSymbolicNames() {
return new String[] {
null, "Backslash", "Colon", "Equals", "Exclamation", "Number", "Dot",
"LineBreak", "Space", "Identifier"
};
}
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
/**
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated
public static final String[] tokenNames;
static {
tokenNames = new String[_SYMBOLIC_NAMES.length];
for (int i = 0; i < tokenNames.length; i++) {
tokenNames[i] = VOCABULARY.getLiteralName(i);
if (tokenNames[i] == null) {
tokenNames[i] = VOCABULARY.getSymbolicName(i);
}
if (tokenNames[i] == null) {
tokenNames[i] = "<INVALID>";
}
}
}
@Override
@Deprecated
public String[] getTokenNames() {
return tokenNames;
}
@Override
public Vocabulary getVocabulary() {
return VOCABULARY;
}
public PropertyPlaceHolderLexer(CharStream input) {
super(input);
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
@Override
public String getGrammarFileName() { return "PropertyPlaceHolder.g4"; }
@Override
public String[] getRuleNames() { return ruleNames; }
@Override
public String getSerializedATN() { return _serializedATN; }
@Override
public String[] getChannelNames() { return channelNames; }
@Override
public String[] getModeNames() { return modeNames; }
@Override
public ATN getATN() { return _ATN; }
public static final String _serializedATN =
"\u0004\u0000\t9\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\u0007"+
"\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0001\u0000\u0001\u0000\u0001"+
"\u0001\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0003\u0001\u0003\u0001"+
"\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001\u0006\u0003\u0006#\b"+
"\u0006\u0001\u0006\u0001\u0006\u0003\u0006\'\b\u0006\u0001\u0007\u0001"+
"\u0007\u0003\u0007+\b\u0007\u0001\b\u0004\b.\b\b\u000b\b\f\b/\u0001\t"+
"\u0001\t\u0001\t\u0001\t\u0003\t6\b\t\u0003\t8\b\t\u0000\u0000\n\u0001"+
"\u0001\u0003\u0002\u0005\u0003\u0007\u0004\t\u0005\u000b\u0006\r\u0007"+
"\u000f\b\u0011\t\u0013\u0000\u0001\u0000\u0002\u0003\u0000\t\t\f\f \u0006"+
"\u0000\n\n\r\r ..::===\u0000\u0001\u0001\u0000\u0000\u0000\u0000\u0003"+
"\u0001\u0000\u0000\u0000\u0000\u0005\u0001\u0000\u0000\u0000\u0000\u0007"+
"\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\u0001\u0015\u0001\u0000"+
"\u0000\u0000\u0003\u0017\u0001\u0000\u0000\u0000\u0005\u0019\u0001\u0000"+
"\u0000\u0000\u0007\u001b\u0001\u0000\u0000\u0000\t\u001d\u0001\u0000\u0000"+
"\u0000\u000b\u001f\u0001\u0000\u0000\u0000\r&\u0001\u0000\u0000\u0000"+
"\u000f*\u0001\u0000\u0000\u0000\u0011-\u0001\u0000\u0000\u0000\u00137"+
"\u0001\u0000\u0000\u0000\u0015\u0016\u0005\\\u0000\u0000\u0016\u0002\u0001"+
"\u0000\u0000\u0000\u0017\u0018\u0005:\u0000\u0000\u0018\u0004\u0001\u0000"+
"\u0000\u0000\u0019\u001a\u0005=\u0000\u0000\u001a\u0006\u0001\u0000\u0000"+
"\u0000\u001b\u001c\u0005!\u0000\u0000\u001c\b\u0001\u0000\u0000\u0000"+
"\u001d\u001e\u0005#\u0000\u0000\u001e\n\u0001\u0000\u0000\u0000\u001f"+
" \u0005.\u0000\u0000 \f\u0001\u0000\u0000\u0000!#\u0005\r\u0000\u0000"+
"\"!\u0001\u0000\u0000\u0000\"#\u0001\u0000\u0000\u0000#$\u0001\u0000\u0000"+
"\u0000$\'\u0005\n\u0000\u0000%\'\u0005\r\u0000\u0000&\"\u0001\u0000\u0000"+
"\u0000&%\u0001\u0000\u0000\u0000\'\u000e\u0001\u0000\u0000\u0000(+\u0007"+
"\u0000\u0000\u0000)+\u0003\r\u0006\u0000*(\u0001\u0000\u0000\u0000*)\u0001"+
"\u0000\u0000\u0000+\u0010\u0001\u0000\u0000\u0000,.\u0003\u0013\t\u0000"+
"-,\u0001\u0000\u0000\u0000./\u0001\u0000\u0000\u0000/-\u0001\u0000\u0000"+
"\u0000/0\u0001\u0000\u0000\u00000\u0012\u0001\u0000\u0000\u000018\b\u0001"+
"\u0000\u000025\u0003\u0001\u0000\u000036\u0003\u0003\u0001\u000046\u0003"+
"\u0005\u0002\u000053\u0001\u0000\u0000\u000054\u0001\u0000\u0000\u0000"+
"68\u0001\u0000\u0000\u000071\u0001\u0000\u0000\u000072\u0001\u0000\u0000"+
"\u00008\u0014\u0001\u0000\u0000\u0000\u0007\u0000\"&*/57\u0000";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
}
}
}

View File

@@ -0,0 +1,80 @@
// Generated from PropertyPlaceHolder.g4 by ANTLR 4.13.1
package org.springframework.ide.vscode.parser.placeholder;
import org.antlr.v4.runtime.tree.ParseTreeListener;
/**
* This interface defines a complete listener for a parse tree produced by
* {@link PropertyPlaceHolderParser}.
*/
public interface PropertyPlaceHolderListener extends ParseTreeListener {
/**
* Enter a parse tree produced by {@link PropertyPlaceHolderParser#start}.
* @param ctx the parse tree
*/
void enterStart(PropertyPlaceHolderParser.StartContext ctx);
/**
* Exit a parse tree produced by {@link PropertyPlaceHolderParser#start}.
* @param ctx the parse tree
*/
void exitStart(PropertyPlaceHolderParser.StartContext ctx);
/**
* Enter a parse tree produced by {@link PropertyPlaceHolderParser#line}.
* @param ctx the parse tree
*/
void enterLine(PropertyPlaceHolderParser.LineContext ctx);
/**
* Exit a parse tree produced by {@link PropertyPlaceHolderParser#line}.
* @param ctx the parse tree
*/
void exitLine(PropertyPlaceHolderParser.LineContext ctx);
/**
* Enter a parse tree produced by {@link PropertyPlaceHolderParser#keyDefaultValuePair}.
* @param ctx the parse tree
*/
void enterKeyDefaultValuePair(PropertyPlaceHolderParser.KeyDefaultValuePairContext ctx);
/**
* Exit a parse tree produced by {@link PropertyPlaceHolderParser#keyDefaultValuePair}.
* @param ctx the parse tree
*/
void exitKeyDefaultValuePair(PropertyPlaceHolderParser.KeyDefaultValuePairContext ctx);
/**
* Enter a parse tree produced by {@link PropertyPlaceHolderParser#defaultValue}.
* @param ctx the parse tree
*/
void enterDefaultValue(PropertyPlaceHolderParser.DefaultValueContext ctx);
/**
* Exit a parse tree produced by {@link PropertyPlaceHolderParser#defaultValue}.
* @param ctx the parse tree
*/
void exitDefaultValue(PropertyPlaceHolderParser.DefaultValueContext ctx);
/**
* Enter a parse tree produced by {@link PropertyPlaceHolderParser#key}.
* @param ctx the parse tree
*/
void enterKey(PropertyPlaceHolderParser.KeyContext ctx);
/**
* Exit a parse tree produced by {@link PropertyPlaceHolderParser#key}.
* @param ctx the parse tree
*/
void exitKey(PropertyPlaceHolderParser.KeyContext ctx);
/**
* Enter a parse tree produced by {@link PropertyPlaceHolderParser#identifier}.
* @param ctx the parse tree
*/
void enterIdentifier(PropertyPlaceHolderParser.IdentifierContext ctx);
/**
* Exit a parse tree produced by {@link PropertyPlaceHolderParser#identifier}.
* @param ctx the parse tree
*/
void exitIdentifier(PropertyPlaceHolderParser.IdentifierContext ctx);
/**
* Enter a parse tree produced by {@link PropertyPlaceHolderParser#value}.
* @param ctx the parse tree
*/
void enterValue(PropertyPlaceHolderParser.ValueContext ctx);
/**
* Exit a parse tree produced by {@link PropertyPlaceHolderParser#value}.
* @param ctx the parse tree
*/
void exitValue(PropertyPlaceHolderParser.ValueContext ctx);
}

View File

@@ -0,0 +1,652 @@
// Generated from PropertyPlaceHolder.g4 by ANTLR 4.13.1
package org.springframework.ide.vscode.parser.placeholder;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.*;
import org.antlr.v4.runtime.tree.*;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"})
public class PropertyPlaceHolderParser extends Parser {
static { RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
public static final int
Backslash=1, Colon=2, Equals=3, Exclamation=4, Number=5, Dot=6, LineBreak=7,
Space=8, Identifier=9;
public static final int
RULE_start = 0, RULE_line = 1, RULE_keyDefaultValuePair = 2, RULE_defaultValue = 3,
RULE_key = 4, RULE_identifier = 5, RULE_value = 6;
private static String[] makeRuleNames() {
return new String[] {
"start", "line", "keyDefaultValuePair", "defaultValue", "key", "identifier",
"value"
};
}
public static final String[] ruleNames = makeRuleNames();
private static String[] makeLiteralNames() {
return new String[] {
null, "'\\'", "':'", "'='", "'!'", "'#'", "'.'"
};
}
private static final String[] _LITERAL_NAMES = makeLiteralNames();
private static String[] makeSymbolicNames() {
return new String[] {
null, "Backslash", "Colon", "Equals", "Exclamation", "Number", "Dot",
"LineBreak", "Space", "Identifier"
};
}
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
/**
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated
public static final String[] tokenNames;
static {
tokenNames = new String[_SYMBOLIC_NAMES.length];
for (int i = 0; i < tokenNames.length; i++) {
tokenNames[i] = VOCABULARY.getLiteralName(i);
if (tokenNames[i] == null) {
tokenNames[i] = VOCABULARY.getSymbolicName(i);
}
if (tokenNames[i] == null) {
tokenNames[i] = "<INVALID>";
}
}
}
@Override
@Deprecated
public String[] getTokenNames() {
return tokenNames;
}
@Override
public Vocabulary getVocabulary() {
return VOCABULARY;
}
@Override
public String getGrammarFileName() { return "PropertyPlaceHolder.g4"; }
@Override
public String[] getRuleNames() { return ruleNames; }
@Override
public String getSerializedATN() { return _serializedATN; }
@Override
public ATN getATN() { return _ATN; }
public PropertyPlaceHolderParser(TokenStream input) {
super(input);
_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
@SuppressWarnings("CheckReturnValue")
public static class StartContext extends ParserRuleContext {
public TerminalNode EOF() { return getToken(PropertyPlaceHolderParser.EOF, 0); }
public List<LineContext> line() {
return getRuleContexts(LineContext.class);
}
public LineContext line(int i) {
return getRuleContext(LineContext.class,i);
}
public StartContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_start; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).enterStart(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).exitStart(this);
}
}
public final StartContext start() throws RecognitionException {
StartContext _localctx = new StartContext(_ctx, getState());
enterRule(_localctx, 0, RULE_start);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(17);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==Space || _la==Identifier) {
{
{
setState(14);
line();
}
}
setState(19);
_errHandler.sync(this);
_la = _input.LA(1);
}
setState(20);
match(EOF);
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
@SuppressWarnings("CheckReturnValue")
public static class LineContext extends ParserRuleContext {
public KeyDefaultValuePairContext keyDefaultValuePair() {
return getRuleContext(KeyDefaultValuePairContext.class,0);
}
public TerminalNode EOF() { return getToken(PropertyPlaceHolderParser.EOF, 0); }
public List<TerminalNode> Space() { return getTokens(PropertyPlaceHolderParser.Space); }
public TerminalNode Space(int i) {
return getToken(PropertyPlaceHolderParser.Space, i);
}
public LineContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_line; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).enterLine(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).exitLine(this);
}
}
public final LineContext line() throws RecognitionException {
LineContext _localctx = new LineContext(_ctx, getState());
enterRule(_localctx, 2, RULE_line);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(25);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==Space) {
{
{
setState(22);
match(Space);
}
}
setState(27);
_errHandler.sync(this);
_la = _input.LA(1);
}
setState(28);
keyDefaultValuePair();
setState(32);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==Space) {
{
{
setState(29);
match(Space);
}
}
setState(34);
_errHandler.sync(this);
_la = _input.LA(1);
}
setState(35);
match(EOF);
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
@SuppressWarnings("CheckReturnValue")
public static class KeyDefaultValuePairContext extends ParserRuleContext {
public KeyContext key() {
return getRuleContext(KeyContext.class,0);
}
public DefaultValueContext defaultValue() {
return getRuleContext(DefaultValueContext.class,0);
}
public KeyDefaultValuePairContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_keyDefaultValuePair; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).enterKeyDefaultValuePair(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).exitKeyDefaultValuePair(this);
}
}
public final KeyDefaultValuePairContext keyDefaultValuePair() throws RecognitionException {
KeyDefaultValuePairContext _localctx = new KeyDefaultValuePairContext(_ctx, getState());
enterRule(_localctx, 4, RULE_keyDefaultValuePair);
try {
setState(41);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,3,_ctx) ) {
case 1:
enterOuterAlt(_localctx, 1);
{
setState(37);
key();
}
break;
case 2:
enterOuterAlt(_localctx, 2);
{
setState(38);
key();
setState(39);
defaultValue();
}
break;
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
@SuppressWarnings("CheckReturnValue")
public static class DefaultValueContext extends ParserRuleContext {
public TerminalNode Colon() { return getToken(PropertyPlaceHolderParser.Colon, 0); }
public ValueContext value() {
return getRuleContext(ValueContext.class,0);
}
public DefaultValueContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_defaultValue; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).enterDefaultValue(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).exitDefaultValue(this);
}
}
public final DefaultValueContext defaultValue() throws RecognitionException {
DefaultValueContext _localctx = new DefaultValueContext(_ctx, getState());
enterRule(_localctx, 6, RULE_defaultValue);
try {
enterOuterAlt(_localctx, 1);
{
setState(43);
match(Colon);
setState(44);
value();
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
@SuppressWarnings("CheckReturnValue")
public static class KeyContext extends ParserRuleContext {
public List<IdentifierContext> identifier() {
return getRuleContexts(IdentifierContext.class);
}
public IdentifierContext identifier(int i) {
return getRuleContext(IdentifierContext.class,i);
}
public List<TerminalNode> Dot() { return getTokens(PropertyPlaceHolderParser.Dot); }
public TerminalNode Dot(int i) {
return getToken(PropertyPlaceHolderParser.Dot, i);
}
public KeyContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_key; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).enterKey(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).exitKey(this);
}
}
public final KeyContext key() throws RecognitionException {
KeyContext _localctx = new KeyContext(_ctx, getState());
enterRule(_localctx, 8, RULE_key);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(46);
identifier();
setState(51);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==Dot) {
{
{
setState(47);
match(Dot);
setState(48);
identifier();
}
}
setState(53);
_errHandler.sync(this);
_la = _input.LA(1);
}
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
@SuppressWarnings("CheckReturnValue")
public static class IdentifierContext extends ParserRuleContext {
public List<TerminalNode> Identifier() { return getTokens(PropertyPlaceHolderParser.Identifier); }
public TerminalNode Identifier(int i) {
return getToken(PropertyPlaceHolderParser.Identifier, i);
}
public IdentifierContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_identifier; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).enterIdentifier(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).exitIdentifier(this);
}
}
public final IdentifierContext identifier() throws RecognitionException {
IdentifierContext _localctx = new IdentifierContext(_ctx, getState());
enterRule(_localctx, 10, RULE_identifier);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(55);
_errHandler.sync(this);
_la = _input.LA(1);
do {
{
{
setState(54);
match(Identifier);
}
}
setState(57);
_errHandler.sync(this);
_la = _input.LA(1);
} while ( _la==Identifier );
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
@SuppressWarnings("CheckReturnValue")
public static class ValueContext extends ParserRuleContext {
public List<TerminalNode> Identifier() { return getTokens(PropertyPlaceHolderParser.Identifier); }
public TerminalNode Identifier(int i) {
return getToken(PropertyPlaceHolderParser.Identifier, i);
}
public List<TerminalNode> Exclamation() { return getTokens(PropertyPlaceHolderParser.Exclamation); }
public TerminalNode Exclamation(int i) {
return getToken(PropertyPlaceHolderParser.Exclamation, i);
}
public List<TerminalNode> Number() { return getTokens(PropertyPlaceHolderParser.Number); }
public TerminalNode Number(int i) {
return getToken(PropertyPlaceHolderParser.Number, i);
}
public List<TerminalNode> Space() { return getTokens(PropertyPlaceHolderParser.Space); }
public TerminalNode Space(int i) {
return getToken(PropertyPlaceHolderParser.Space, i);
}
public List<TerminalNode> Backslash() { return getTokens(PropertyPlaceHolderParser.Backslash); }
public TerminalNode Backslash(int i) {
return getToken(PropertyPlaceHolderParser.Backslash, i);
}
public List<TerminalNode> LineBreak() { return getTokens(PropertyPlaceHolderParser.LineBreak); }
public TerminalNode LineBreak(int i) {
return getToken(PropertyPlaceHolderParser.LineBreak, i);
}
public List<TerminalNode> Equals() { return getTokens(PropertyPlaceHolderParser.Equals); }
public TerminalNode Equals(int i) {
return getToken(PropertyPlaceHolderParser.Equals, i);
}
public List<TerminalNode> Colon() { return getTokens(PropertyPlaceHolderParser.Colon); }
public TerminalNode Colon(int i) {
return getToken(PropertyPlaceHolderParser.Colon, i);
}
public List<TerminalNode> Dot() { return getTokens(PropertyPlaceHolderParser.Dot); }
public TerminalNode Dot(int i) {
return getToken(PropertyPlaceHolderParser.Dot, i);
}
public ValueContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_value; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).enterValue(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof PropertyPlaceHolderListener ) ((PropertyPlaceHolderListener)listener).exitValue(this);
}
}
public final ValueContext value() throws RecognitionException {
ValueContext _localctx = new ValueContext(_ctx, getState());
enterRule(_localctx, 12, RULE_value);
try {
int _alt;
enterOuterAlt(_localctx, 1);
{
setState(72);
_errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,7,_ctx);
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
if ( _alt==1 ) {
{
setState(70);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) {
case 1:
{
setState(59);
match(Identifier);
}
break;
case 2:
{
setState(60);
match(Exclamation);
}
break;
case 3:
{
setState(61);
match(Number);
}
break;
case 4:
{
setState(62);
match(Space);
}
break;
case 5:
{
setState(63);
match(Backslash);
setState(64);
match(Backslash);
}
break;
case 6:
{
setState(65);
match(Backslash);
setState(66);
match(LineBreak);
}
break;
case 7:
{
setState(67);
match(Equals);
}
break;
case 8:
{
setState(68);
match(Colon);
}
break;
case 9:
{
setState(69);
match(Dot);
}
break;
}
}
}
setState(74);
_errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,7,_ctx);
}
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static final String _serializedATN =
"\u0004\u0001\tL\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\u0001\u0000\u0005\u0000\u0010"+
"\b\u0000\n\u0000\f\u0000\u0013\t\u0000\u0001\u0000\u0001\u0000\u0001\u0001"+
"\u0005\u0001\u0018\b\u0001\n\u0001\f\u0001\u001b\t\u0001\u0001\u0001\u0001"+
"\u0001\u0005\u0001\u001f\b\u0001\n\u0001\f\u0001\"\t\u0001\u0001\u0001"+
"\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0003\u0002"+
"*\b\u0002\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0004\u0001\u0004"+
"\u0001\u0004\u0005\u00042\b\u0004\n\u0004\f\u00045\t\u0004\u0001\u0005"+
"\u0004\u00058\b\u0005\u000b\u0005\f\u00059\u0001\u0006\u0001\u0006\u0001"+
"\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001"+
"\u0006\u0001\u0006\u0001\u0006\u0005\u0006G\b\u0006\n\u0006\f\u0006J\t"+
"\u0006\u0001\u0006\u0000\u0000\u0007\u0000\u0002\u0004\u0006\b\n\f\u0000"+
"\u0000S\u0000\u0011\u0001\u0000\u0000\u0000\u0002\u0019\u0001\u0000\u0000"+
"\u0000\u0004)\u0001\u0000\u0000\u0000\u0006+\u0001\u0000\u0000\u0000\b"+
".\u0001\u0000\u0000\u0000\n7\u0001\u0000\u0000\u0000\fH\u0001\u0000\u0000"+
"\u0000\u000e\u0010\u0003\u0002\u0001\u0000\u000f\u000e\u0001\u0000\u0000"+
"\u0000\u0010\u0013\u0001\u0000\u0000\u0000\u0011\u000f\u0001\u0000\u0000"+
"\u0000\u0011\u0012\u0001\u0000\u0000\u0000\u0012\u0014\u0001\u0000\u0000"+
"\u0000\u0013\u0011\u0001\u0000\u0000\u0000\u0014\u0015\u0005\u0000\u0000"+
"\u0001\u0015\u0001\u0001\u0000\u0000\u0000\u0016\u0018\u0005\b\u0000\u0000"+
"\u0017\u0016\u0001\u0000\u0000\u0000\u0018\u001b\u0001\u0000\u0000\u0000"+
"\u0019\u0017\u0001\u0000\u0000\u0000\u0019\u001a\u0001\u0000\u0000\u0000"+
"\u001a\u001c\u0001\u0000\u0000\u0000\u001b\u0019\u0001\u0000\u0000\u0000"+
"\u001c \u0003\u0004\u0002\u0000\u001d\u001f\u0005\b\u0000\u0000\u001e"+
"\u001d\u0001\u0000\u0000\u0000\u001f\"\u0001\u0000\u0000\u0000 \u001e"+
"\u0001\u0000\u0000\u0000 !\u0001\u0000\u0000\u0000!#\u0001\u0000\u0000"+
"\u0000\" \u0001\u0000\u0000\u0000#$\u0005\u0000\u0000\u0001$\u0003\u0001"+
"\u0000\u0000\u0000%*\u0003\b\u0004\u0000&\'\u0003\b\u0004\u0000\'(\u0003"+
"\u0006\u0003\u0000(*\u0001\u0000\u0000\u0000)%\u0001\u0000\u0000\u0000"+
")&\u0001\u0000\u0000\u0000*\u0005\u0001\u0000\u0000\u0000+,\u0005\u0002"+
"\u0000\u0000,-\u0003\f\u0006\u0000-\u0007\u0001\u0000\u0000\u0000.3\u0003"+
"\n\u0005\u0000/0\u0005\u0006\u0000\u000002\u0003\n\u0005\u00001/\u0001"+
"\u0000\u0000\u000025\u0001\u0000\u0000\u000031\u0001\u0000\u0000\u0000"+
"34\u0001\u0000\u0000\u00004\t\u0001\u0000\u0000\u000053\u0001\u0000\u0000"+
"\u000068\u0005\t\u0000\u000076\u0001\u0000\u0000\u000089\u0001\u0000\u0000"+
"\u000097\u0001\u0000\u0000\u00009:\u0001\u0000\u0000\u0000:\u000b\u0001"+
"\u0000\u0000\u0000;G\u0005\t\u0000\u0000<G\u0005\u0004\u0000\u0000=G\u0005"+
"\u0005\u0000\u0000>G\u0005\b\u0000\u0000?@\u0005\u0001\u0000\u0000@G\u0005"+
"\u0001\u0000\u0000AB\u0005\u0001\u0000\u0000BG\u0005\u0007\u0000\u0000"+
"CG\u0005\u0003\u0000\u0000DG\u0005\u0002\u0000\u0000EG\u0005\u0006\u0000"+
"\u0000F;\u0001\u0000\u0000\u0000F<\u0001\u0000\u0000\u0000F=\u0001\u0000"+
"\u0000\u0000F>\u0001\u0000\u0000\u0000F?\u0001\u0000\u0000\u0000FA\u0001"+
"\u0000\u0000\u0000FC\u0001\u0000\u0000\u0000FD\u0001\u0000\u0000\u0000"+
"FE\u0001\u0000\u0000\u0000GJ\u0001\u0000\u0000\u0000HF\u0001\u0000\u0000"+
"\u0000HI\u0001\u0000\u0000\u0000I\r\u0001\u0000\u0000\u0000JH\u0001\u0000"+
"\u0000\u0000\b\u0011\u0019 )39FH";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
}
}
}

View File

@@ -38,8 +38,8 @@ public class SpelLexer extends Lexer {
FALSE=44, NEW=45, NULL=46, T=47, MATCHES=48, GT_KEYWORD=49, GE_KEYWORD=50,
LE_KEYWORD=51, LT_KEYWORD=52, EQ_KEYWORD=53, NE_KEYWORD=54, IDENTIFIER=55,
REAL_LITERAL=56, INTEGER_LITERAL=57, STRING_LITERAL=58, SINGLE_QUOTED_STRING=59,
DOUBLE_QUOTED_STRING=60, ESCAPED_BACKTICK=61, SPEL_IN_TEMPLATE_STRING_OPEN=62,
TEMPLATE_TEXT=63;
DOUBLE_QUOTED_STRING=60, PROPERTY_PLACE_HOLDER=61, ESCAPED_BACKTICK=62,
SPEL_IN_TEMPLATE_STRING_OPEN=63, TEMPLATE_TEXT=64;
public static final int
IN_TEMPLATE_STRING=1;
public static String[] channelNames = {
@@ -60,10 +60,10 @@ public class SpelLexer extends Lexer {
"LT", "LCURLY", "RCURLY", "BACKTICK", "OR", "AND", "TRUE", "FALSE", "NEW",
"NULL", "T", "MATCHES", "GT_KEYWORD", "GE_KEYWORD", "LE_KEYWORD", "LT_KEYWORD",
"EQ_KEYWORD", "NE_KEYWORD", "IDENTIFIER", "REAL_LITERAL", "INTEGER_LITERAL",
"STRING_LITERAL", "SINGLE_QUOTED_STRING", "DOUBLE_QUOTED_STRING", "INTEGER_TYPE_SUFFIX",
"HEX_DIGIT", "DECIMAL_DIGIT", "EXPONENT_PART", "SIGN", "REAL_TYPE_SUFFIX",
"ALPHABETIC", "DIGIT", "ESCAPED_BACKTICK", "SPEL_IN_TEMPLATE_STRING_OPEN",
"TEMPLATE_TEXT", "BACKTICK_IN_TEMPLATE"
"STRING_LITERAL", "SINGLE_QUOTED_STRING", "DOUBLE_QUOTED_STRING", "PROPERTY_PLACE_HOLDER",
"INTEGER_TYPE_SUFFIX", "HEX_DIGIT", "DECIMAL_DIGIT", "EXPONENT_PART",
"SIGN", "REAL_TYPE_SUFFIX", "ALPHABETIC", "DIGIT", "ESCAPED_BACKTICK",
"SPEL_IN_TEMPLATE_STRING_OPEN", "TEMPLATE_TEXT", "BACKTICK_IN_TEMPLATE"
};
}
public static final String[] ruleNames = makeRuleNames();
@@ -76,7 +76,7 @@ public class SpelLexer extends Lexer {
"'?:'", "'?.'", "'?'", "'$['", "'>='", "'>'", "'<='", "'<'", null, null,
null, "'or'", "'and'", "'true'", "'false'", "'new'", "'null'", "'T'",
"'matches'", "'gt'", "'ge'", "'le'", "'lt'", "'eq'", "'ne'", null, null,
null, null, null, null, "'``'"
null, null, null, null, null, "'``'"
};
}
private static final String[] _LITERAL_NAMES = makeLiteralNames();
@@ -90,8 +90,8 @@ public class SpelLexer extends Lexer {
"LCURLY", "RCURLY", "BACKTICK", "OR", "AND", "TRUE", "FALSE", "NEW",
"NULL", "T", "MATCHES", "GT_KEYWORD", "GE_KEYWORD", "LE_KEYWORD", "LT_KEYWORD",
"EQ_KEYWORD", "NE_KEYWORD", "IDENTIFIER", "REAL_LITERAL", "INTEGER_LITERAL",
"STRING_LITERAL", "SINGLE_QUOTED_STRING", "DOUBLE_QUOTED_STRING", "ESCAPED_BACKTICK",
"SPEL_IN_TEMPLATE_STRING_OPEN", "TEMPLATE_TEXT"
"STRING_LITERAL", "SINGLE_QUOTED_STRING", "DOUBLE_QUOTED_STRING", "PROPERTY_PLACE_HOLDER",
"ESCAPED_BACKTICK", "SPEL_IN_TEMPLATE_STRING_OPEN", "TEMPLATE_TEXT"
};
}
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
@@ -164,7 +164,7 @@ public class SpelLexer extends Lexer {
case 39:
RCURLY_action((RuleContext)_localctx, actionIndex);
break;
case 70:
case 71:
SPEL_IN_TEMPLATE_STRING_OPEN_action((RuleContext)_localctx, actionIndex);
break;
}
@@ -196,7 +196,7 @@ public class SpelLexer extends Lexer {
}
public static final String _serializedATN =
"\u0004\u0000?\u01d2\u0006\uffff\uffff\u0006\uffff\uffff\u0002\u0000\u0007"+
"\u0004\u0000@\u01df\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\u0007\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n"+
@@ -215,448 +215,457 @@ public class SpelLexer extends Lexer {
"9\u00079\u0002:\u0007:\u0002;\u0007;\u0002<\u0007<\u0002=\u0007=\u0002"+
">\u0007>\u0002?\u0007?\u0002@\u0007@\u0002A\u0007A\u0002B\u0007B\u0002"+
"C\u0007C\u0002D\u0007D\u0002E\u0007E\u0002F\u0007F\u0002G\u0007G\u0002"+
"H\u0007H\u0001\u0000\u0001\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0003"+
"\u0001\u009a\b\u0001\u0001\u0002\u0004\u0002\u009d\b\u0002\u000b\u0002"+
"\f\u0002\u009e\u0001\u0002\u0001\u0002\u0001\u0003\u0001\u0003\u0001\u0003"+
"\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0006"+
"\u0001\u0006\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001\t\u0001\t\u0001"+
"\n\u0001\n\u0001\u000b\u0001\u000b\u0001\f\u0001\f\u0001\r\u0001\r\u0001"+
"\u000e\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001"+
"\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001"+
"\u0013\u0001\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001"+
"\u0016\u0001\u0016\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0018\u0001"+
"\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u001a\u0001\u001a\u0001"+
"\u001a\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001c\u0001"+
"\u001d\u0001\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001e\u0001"+
"\u001f\u0001\u001f\u0001\u001f\u0001 \u0001 \u0001!\u0001!\u0001!\u0001"+
"\"\u0001\"\u0001\"\u0001#\u0001#\u0001$\u0001$\u0001$\u0001%\u0001%\u0001"+
"&\u0001&\u0001&\u0001&\u0001&\u0001\'\u0001\'\u0001\'\u0001\'\u0001\'"+
"\u0001(\u0001(\u0001(\u0001(\u0001)\u0001)\u0001)\u0001*\u0001*\u0001"+
"*\u0001*\u0001+\u0001+\u0001+\u0001+\u0001+\u0001,\u0001,\u0001,\u0001"+
",\u0001,\u0001,\u0001-\u0001-\u0001-\u0001-\u0001.\u0001.\u0001.\u0001"+
".\u0001.\u0001/\u0001/\u00010\u00010\u00010\u00010\u00010\u00010\u0001"+
"0\u00010\u00011\u00011\u00011\u00012\u00012\u00012\u00013\u00013\u0001"+
"3\u00014\u00014\u00014\u00015\u00015\u00015\u00016\u00016\u00016\u0001"+
"7\u00017\u00037\u013e\b7\u00017\u00017\u00017\u00057\u0143\b7\n7\f7\u0146"+
"\t7\u00018\u00018\u00048\u014a\b8\u000b8\f8\u014b\u00018\u00038\u014f"+
"\b8\u00018\u00038\u0152\b8\u00018\u00048\u0155\b8\u000b8\f8\u0156\u0001"+
"8\u00018\u00048\u015b\b8\u000b8\f8\u015c\u00018\u00038\u0160\b8\u0001"+
"8\u00038\u0163\b8\u00018\u00048\u0166\b8\u000b8\f8\u0167\u00018\u0001"+
"8\u00038\u016c\b8\u00018\u00048\u016f\b8\u000b8\f8\u0170\u00018\u0001"+
"8\u00038\u0175\b8\u00019\u00049\u0178\b9\u000b9\f9\u0179\u00019\u0003"+
"9\u017d\b9\u0001:\u0001:\u0003:\u0181\b:\u0001;\u0001;\u0001;\u0001;\u0005"+
";\u0187\b;\n;\f;\u018a\t;\u0001;\u0001;\u0001<\u0001<\u0001<\u0001<\u0005"+
"<\u0192\b<\n<\f<\u0195\t<\u0001<\u0001<\u0001=\u0001=\u0001>\u0001>\u0001"+
"?\u0001?\u0001@\u0001@\u0005@\u01a1\b@\n@\f@\u01a4\t@\u0001@\u0004@\u01a7"+
"\b@\u000b@\f@\u01a8\u0001@\u0001@\u0005@\u01ad\b@\n@\f@\u01b0\t@\u0001"+
"@\u0004@\u01b3\b@\u000b@\f@\u01b4\u0003@\u01b7\b@\u0001A\u0001A\u0001"+
"B\u0001B\u0001C\u0003C\u01be\bC\u0001D\u0001D\u0001E\u0001E\u0001E\u0001"+
"F\u0001F\u0001F\u0001F\u0001F\u0001F\u0001F\u0001G\u0001G\u0001H\u0001"+
"H\u0001H\u0001H\u0001H\u0000\u0000I\u0002\u0001\u0004\u0000\u0006\u0002"+
"\b\u0003\n\u0004\f\u0005\u000e\u0006\u0010\u0007\u0012\b\u0014\t\u0016"+
"\n\u0018\u000b\u001a\f\u001c\r\u001e\u000e \u000f\"\u0010$\u0011&\u0012"+
"(\u0013*\u0014,\u0015.\u00160\u00172\u00184\u00196\u001a8\u001b:\u001c"+
"<\u001d>\u001e@\u001fB D!F\"H#J$L%N&P\'R(T)V*X+Z,\\-^.`/b0d1f2h3j4l5n"+
"6p7r8t9v:x;z<|\u0000~\u0000\u0080\u0000\u0082\u0000\u0084\u0000\u0086"+
"\u0000\u0088\u0000\u008a\u0000\u008c=\u008e>\u0090?\u0092\u0000\u0002"+
"\u0000\u0001\f\u0003\u0000\n\n\r\r\u2028\u2029\u0003\u0000\t\n\r\r \u0002"+
"\u0000$$__\u0002\u0000\n\n\'\'\u0002\u0000\n\n\"\"\u0002\u0000LLll\u0003"+
"\u000009AFaf\u0001\u000009\u0002\u0000++--\u0004\u0000DDFFddff\u0293\u0000"+
"AZaz\u00aa\u00aa\u00b5\u00b5\u00ba\u00ba\u00c0\u00d6\u00d8\u00f6\u00f8"+
"\u02c1\u02c6\u02d1\u02e0\u02e4\u02ec\u02ec\u02ee\u02ee\u0370\u0374\u0376"+
"\u0377\u037a\u037d\u037f\u037f\u0386\u0386\u0388\u038a\u038c\u038c\u038e"+
"\u03a1\u03a3\u03f5\u03f7\u0481\u048a\u052f\u0531\u0556\u0559\u0559\u0560"+
"\u0588\u05d0\u05ea\u05ef\u05f2\u0620\u064a\u066e\u066f\u0671\u06d3\u06d5"+
"\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa\u06fc\u06ff\u06ff\u0710\u0710\u0712"+
"\u072f\u074d\u07a5\u07b1\u07b1\u07ca\u07ea\u07f4\u07f5\u07fa\u07fa\u0800"+
"\u0815\u081a\u081a\u0824\u0824\u0828\u0828\u0840\u0858\u0860\u086a\u0870"+
"\u0887\u0889\u088e\u08a0\u08c9\u0904\u0939\u093d\u093d\u0950\u0950\u0958"+
"\u0961\u0971\u0980\u0985\u098c\u098f\u0990\u0993\u09a8\u09aa\u09b0\u09b2"+
"\u09b2\u09b6\u09b9\u09bd\u09bd\u09ce\u09ce\u09dc\u09dd\u09df\u09e1\u09f0"+
"\u09f1\u09fc\u09fc\u0a05\u0a0a\u0a0f\u0a10\u0a13\u0a28\u0a2a\u0a30\u0a32"+
"\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59\u0a5c\u0a5e\u0a5e\u0a72\u0a74\u0a85"+
"\u0a8d\u0a8f\u0a91\u0a93\u0aa8\u0aaa\u0ab0\u0ab2\u0ab3\u0ab5\u0ab9\u0abd"+
"\u0abd\u0ad0\u0ad0\u0ae0\u0ae1\u0af9\u0af9\u0b05\u0b0c\u0b0f\u0b10\u0b13"+
"\u0b28\u0b2a\u0b30\u0b32\u0b33\u0b35\u0b39\u0b3d\u0b3d\u0b5c\u0b5d\u0b5f"+
"\u0b61\u0b71\u0b71\u0b83\u0b83\u0b85\u0b8a\u0b8e\u0b90\u0b92\u0b95\u0b99"+
"\u0b9a\u0b9c\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8\u0baa\u0bae\u0bb9\u0bd0"+
"\u0bd0\u0c05\u0c0c\u0c0e\u0c10\u0c12\u0c28\u0c2a\u0c39\u0c3d\u0c3d\u0c58"+
"\u0c5a\u0c5d\u0c5d\u0c60\u0c61\u0c80\u0c80\u0c85\u0c8c\u0c8e\u0c90\u0c92"+
"\u0ca8\u0caa\u0cb3\u0cb5\u0cb9\u0cbd\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1"+
"\u0cf2\u0d04\u0d0c\u0d0e\u0d10\u0d12\u0d3a\u0d3d\u0d3d\u0d4e\u0d4e\u0d54"+
"\u0d56\u0d5f\u0d61\u0d7a\u0d7f\u0d85\u0d96\u0d9a\u0db1\u0db3\u0dbb\u0dbd"+
"\u0dbd\u0dc0\u0dc6\u0e01\u0e30\u0e32\u0e33\u0e40\u0e46\u0e81\u0e82\u0e84"+
"\u0e84\u0e86\u0e8a\u0e8c\u0ea3\u0ea5\u0ea5\u0ea7\u0eb0\u0eb2\u0eb3\u0ebd"+
"\u0ebd\u0ec0\u0ec4\u0ec6\u0ec6\u0edc\u0edf\u0f00\u0f00\u0f40\u0f47\u0f49"+
"\u0f6c\u0f88\u0f8c\u1000\u102a\u103f\u103f\u1050\u1055\u105a\u105d\u1061"+
"\u1061\u1065\u1066\u106e\u1070\u1075\u1081\u108e\u108e\u10a0\u10c5\u10c7"+
"\u10c7\u10cd\u10cd\u10d0\u10fa\u10fc\u1248\u124a\u124d\u1250\u1256\u1258"+
"\u1258\u125a\u125d\u1260\u1288\u128a\u128d\u1290\u12b0\u12b2\u12b5\u12b8"+
"\u12be\u12c0\u12c0\u12c2\u12c5\u12c8\u12d6\u12d8\u1310\u1312\u1315\u1318"+
"\u135a\u1380\u138f\u13a0\u13f5\u13f8\u13fd\u1401\u166c\u166f\u167f\u1681"+
"\u169a\u16a0\u16ea\u16f1\u16f8\u1700\u1711\u171f\u1731\u1740\u1751\u1760"+
"\u176c\u176e\u1770\u1780\u17b3\u17d7\u17d7\u17dc\u17dc\u1820\u1878\u1880"+
"\u1884\u1887\u18a8\u18aa\u18aa\u18b0\u18f5\u1900\u191e\u1950\u196d\u1970"+
"\u1974\u1980\u19ab\u19b0\u19c9\u1a00\u1a16\u1a20\u1a54\u1aa7\u1aa7\u1b05"+
"\u1b33\u1b45\u1b4c\u1b83\u1ba0\u1bae\u1baf\u1bba\u1be5\u1c00\u1c23\u1c4d"+
"\u1c4f\u1c5a\u1c7d\u1c80\u1c88\u1c90\u1cba\u1cbd\u1cbf\u1ce9\u1cec\u1cee"+
"\u1cf3\u1cf5\u1cf6\u1cfa\u1cfa\u1d00\u1dbf\u1e00\u1f15\u1f18\u1f1d\u1f20"+
"\u1f45\u1f48\u1f4d\u1f50\u1f57\u1f59\u1f59\u1f5b\u1f5b\u1f5d\u1f5d\u1f5f"+
"\u1f7d\u1f80\u1fb4\u1fb6\u1fbc\u1fbe\u1fbe\u1fc2\u1fc4\u1fc6\u1fcc\u1fd0"+
"\u1fd3\u1fd6\u1fdb\u1fe0\u1fec\u1ff2\u1ff4\u1ff6\u1ffc\u2071\u2071\u207f"+
"\u207f\u2090\u209c\u2102\u2102\u2107\u2107\u210a\u2113\u2115\u2115\u2119"+
"\u211d\u2124\u2124\u2126\u2126\u2128\u2128\u212a\u212d\u212f\u2139\u213c"+
"\u213f\u2145\u2149\u214e\u214e\u2183\u2184\u2c00\u2ce4\u2ceb\u2cee\u2cf2"+
"\u2cf3\u2d00\u2d25\u2d27\u2d27\u2d2d\u2d2d\u2d30\u2d67\u2d6f\u2d6f\u2d80"+
"\u2d96\u2da0\u2da6\u2da8\u2dae\u2db0\u2db6\u2db8\u2dbe\u2dc0\u2dc6\u2dc8"+
"\u2dce\u2dd0\u2dd6\u2dd8\u2dde\u2e2f\u2e2f\u3005\u3006\u3031\u3035\u303b"+
"\u303c\u3041\u3096\u309d\u309f\u30a1\u30fa\u30fc\u30ff\u3105\u312f\u3131"+
"\u318e\u31a0\u31bf\u31f0\u31ff\u3400\u4dbf\u4e00\u8000\ua48c\u8000\ua4d0"+
"\u8000\ua4fd\u8000\ua500\u8000\ua60c\u8000\ua610\u8000\ua61f\u8000\ua62a"+
"\u8000\ua62b\u8000\ua640\u8000\ua66e\u8000\ua67f\u8000\ua69d\u8000\ua6a0"+
"\u8000\ua6e5\u8000\ua717\u8000\ua71f\u8000\ua722\u8000\ua788\u8000\ua78b"+
"\u8000\ua7ca\u8000\ua7d0\u8000\ua7d1\u8000\ua7d3\u8000\ua7d3\u8000\ua7d5"+
"\u8000\ua7d9\u8000\ua7f2\u8000\ua801\u8000\ua803\u8000\ua805\u8000\ua807"+
"\u8000\ua80a\u8000\ua80c\u8000\ua822\u8000\ua840\u8000\ua873\u8000\ua882"+
"\u8000\ua8b3\u8000\ua8f2\u8000\ua8f7\u8000\ua8fb\u8000\ua8fb\u8000\ua8fd"+
"\u8000\ua8fe\u8000\ua90a\u8000\ua925\u8000\ua930\u8000\ua946\u8000\ua960"+
"\u8000\ua97c\u8000\ua984\u8000\ua9b2\u8000\ua9cf\u8000\ua9cf\u8000\ua9e0"+
"\u8000\ua9e4\u8000\ua9e6\u8000\ua9ef\u8000\ua9fa\u8000\ua9fe\u8000\uaa00"+
"\u8000\uaa28\u8000\uaa40\u8000\uaa42\u8000\uaa44\u8000\uaa4b\u8000\uaa60"+
"\u8000\uaa76\u8000\uaa7a\u8000\uaa7a\u8000\uaa7e\u8000\uaaaf\u8000\uaab1"+
"\u8000\uaab1\u8000\uaab5\u8000\uaab6\u8000\uaab9\u8000\uaabd\u8000\uaac0"+
"\u8000\uaac0\u8000\uaac2\u8000\uaac2\u8000\uaadb\u8000\uaadd\u8000\uaae0"+
"\u8000\uaaea\u8000\uaaf2\u8000\uaaf4\u8000\uab01\u8000\uab06\u8000\uab09"+
"\u8000\uab0e\u8000\uab11\u8000\uab16\u8000\uab20\u8000\uab26\u8000\uab28"+
"\u8000\uab2e\u8000\uab30\u8000\uab5a\u8000\uab5c\u8000\uab69\u8000\uab70"+
"\u8000\uabe2\u8000\uac00\u8000\ud7a3\u8000\ud7b0\u8000\ud7c6\u8000\ud7cb"+
"\u8000\ud7fb\u8000\uf900\u8000\ufa6d\u8000\ufa70\u8000\ufad9\u8000\ufb00"+
"\u8000\ufb06\u8000\ufb13\u8000\ufb17\u8000\ufb1d\u8000\ufb1d\u8000\ufb1f"+
"\u8000\ufb28\u8000\ufb2a\u8000\ufb36\u8000\ufb38\u8000\ufb3c\u8000\ufb3e"+
"\u8000\ufb3e\u8000\ufb40\u8000\ufb41\u8000\ufb43\u8000\ufb44\u8000\ufb46"+
"\u8000\ufbb1\u8000\ufbd3\u8000\ufd3d\u8000\ufd50\u8000\ufd8f\u8000\ufd92"+
"\u8000\ufdc7\u8000\ufdf0\u8000\ufdfb\u8000\ufe70\u8000\ufe74\u8000\ufe76"+
"\u8000\ufefc\u8000\uff21\u8000\uff3a\u8000\uff41\u8000\uff5a\u8000\uff66"+
"\u8000\uffbe\u8000\uffc2\u8000\uffc7\u8000\uffca\u8000\uffcf\u8000\uffd2"+
"\u8000\uffd7\u8000\uffda\u8000\uffdc\u8001\u0000\u8001\u000b\u8001\r\u8001"+
"&\u8001(\u8001:\u8001<\u8001=\u8001?\u8001M\u8001P\u8001]\u8001\u0080"+
"\u8001\u00fa\u8001\u0280\u8001\u029c\u8001\u02a0\u8001\u02d0\u8001\u0300"+
"\u8001\u031f\u8001\u032d\u8001\u0340\u8001\u0342\u8001\u0349\u8001\u0350"+
"\u8001\u0375\u8001\u0380\u8001\u039d\u8001\u03a0\u8001\u03c3\u8001\u03c8"+
"\u8001\u03cf\u8001\u0400\u8001\u049d\u8001\u04b0\u8001\u04d3\u8001\u04d8"+
"\u8001\u04fb\u8001\u0500\u8001\u0527\u8001\u0530\u8001\u0563\u8001\u0570"+
"\u8001\u057a\u8001\u057c\u8001\u058a\u8001\u058c\u8001\u0592\u8001\u0594"+
"\u8001\u0595\u8001\u0597\u8001\u05a1\u8001\u05a3\u8001\u05b1\u8001\u05b3"+
"\u8001\u05b9\u8001\u05bb\u8001\u05bc\u8001\u0600\u8001\u0736\u8001\u0740"+
"\u8001\u0755\u8001\u0760\u8001\u0767\u8001\u0780\u8001\u0785\u8001\u0787"+
"\u8001\u07b0\u8001\u07b2\u8001\u07ba\u8001\u0800\u8001\u0805\u8001\u0808"+
"\u8001\u0808\u8001\u080a\u8001\u0835\u8001\u0837\u8001\u0838\u8001\u083c"+
"\u8001\u083c\u8001\u083f\u8001\u0855\u8001\u0860\u8001\u0876\u8001\u0880"+
"\u8001\u089e\u8001\u08e0\u8001\u08f2\u8001\u08f4\u8001\u08f5\u8001\u0900"+
"\u8001\u0915\u8001\u0920\u8001\u0939\u8001\u0980\u8001\u09b7\u8001\u09be"+
"\u8001\u09bf\u8001\u0a00\u8001\u0a00\u8001\u0a10\u8001\u0a13\u8001\u0a15"+
"\u8001\u0a17\u8001\u0a19\u8001\u0a35\u8001\u0a60\u8001\u0a7c\u8001\u0a80"+
"\u8001\u0a9c\u8001\u0ac0\u8001\u0ac7\u8001\u0ac9\u8001\u0ae4\u8001\u0b00"+
"\u8001\u0b35\u8001\u0b40\u8001\u0b55\u8001\u0b60\u8001\u0b72\u8001\u0b80"+
"\u8001\u0b91\u8001\u0c00\u8001\u0c48\u8001\u0c80\u8001\u0cb2\u8001\u0cc0"+
"\u8001\u0cf2\u8001\u0d00\u8001\u0d23\u8001\u0e80\u8001\u0ea9\u8001\u0eb0"+
"\u8001\u0eb1\u8001\u0f00\u8001\u0f1c\u8001\u0f27\u8001\u0f27\u8001\u0f30"+
"\u8001\u0f45\u8001\u0f70\u8001\u0f81\u8001\u0fb0\u8001\u0fc4\u8001\u0fe0"+
"\u8001\u0ff6\u8001\u1003\u8001\u1037\u8001\u1071\u8001\u1072\u8001\u1075"+
"\u8001\u1075\u8001\u1083\u8001\u10af\u8001\u10d0\u8001\u10e8\u8001\u1103"+
"\u8001\u1126\u8001\u1144\u8001\u1144\u8001\u1147\u8001\u1147\u8001\u1150"+
"\u8001\u1172\u8001\u1176\u8001\u1176\u8001\u1183\u8001\u11b2\u8001\u11c1"+
"\u8001\u11c4\u8001\u11da\u8001\u11da\u8001\u11dc\u8001\u11dc\u8001\u1200"+
"\u8001\u1211\u8001\u1213\u8001\u122b\u8001\u123f\u8001\u1240\u8001\u1280"+
"\u8001\u1286\u8001\u1288\u8001\u1288\u8001\u128a\u8001\u128d\u8001\u128f"+
"\u8001\u129d\u8001\u129f\u8001\u12a8\u8001\u12b0\u8001\u12de\u8001\u1305"+
"\u8001\u130c\u8001\u130f\u8001\u1310\u8001\u1313\u8001\u1328\u8001\u132a"+
"\u8001\u1330\u8001\u1332\u8001\u1333\u8001\u1335\u8001\u1339\u8001\u133d"+
"\u8001\u133d\u8001\u1350\u8001\u1350\u8001\u135d\u8001\u1361\u8001\u1400"+
"\u8001\u1434\u8001\u1447\u8001\u144a\u8001\u145f\u8001\u1461\u8001\u1480"+
"\u8001\u14af\u8001\u14c4\u8001\u14c5\u8001\u14c7\u8001\u14c7\u8001\u1580"+
"\u8001\u15ae\u8001\u15d8\u8001\u15db\u8001\u1600\u8001\u162f\u8001\u1644"+
"\u8001\u1644\u8001\u1680\u8001\u16aa\u8001\u16b8\u8001\u16b8\u8001\u1700"+
"\u8001\u171a\u8001\u1740\u8001\u1746\u8001\u1800\u8001\u182b\u8001\u18a0"+
"\u8001\u18df\u8001\u18ff\u8001\u1906\u8001\u1909\u8001\u1909\u8001\u190c"+
"\u8001\u1913\u8001\u1915\u8001\u1916\u8001\u1918\u8001\u192f\u8001\u193f"+
"\u8001\u193f\u8001\u1941\u8001\u1941\u8001\u19a0\u8001\u19a7\u8001\u19aa"+
"\u8001\u19d0\u8001\u19e1\u8001\u19e1\u8001\u19e3\u8001\u19e3\u8001\u1a00"+
"\u8001\u1a00\u8001\u1a0b\u8001\u1a32\u8001\u1a3a\u8001\u1a3a\u8001\u1a50"+
"\u8001\u1a50\u8001\u1a5c\u8001\u1a89\u8001\u1a9d\u8001\u1a9d\u8001\u1ab0"+
"\u8001\u1af8\u8001\u1c00\u8001\u1c08\u8001\u1c0a\u8001\u1c2e\u8001\u1c40"+
"\u8001\u1c40\u8001\u1c72\u8001\u1c8f\u8001\u1d00\u8001\u1d06\u8001\u1d08"+
"\u8001\u1d09\u8001\u1d0b\u8001\u1d30\u8001\u1d46\u8001\u1d46\u8001\u1d60"+
"\u8001\u1d65\u8001\u1d67\u8001\u1d68\u8001\u1d6a\u8001\u1d89\u8001\u1d98"+
"\u8001\u1d98\u8001\u1ee0\u8001\u1ef2\u8001\u1f02\u8001\u1f02\u8001\u1f04"+
"\u8001\u1f10\u8001\u1f12\u8001\u1f33\u8001\u1fb0\u8001\u1fb0\u8001\u2000"+
"\u8001\u2399\u8001\u2480\u8001\u2543\u8001\u2f90\u8001\u2ff0\u8001\u3000"+
"\u8001\u342f\u8001\u3441\u8001\u3446\u8001\u4400\u8001\u4646\u8001\u6800"+
"\u8001\u6a38\u8001\u6a40\u8001\u6a5e\u8001\u6a70\u8001\u6abe\u8001\u6ad0"+
"\u8001\u6aed\u8001\u6b00\u8001\u6b2f\u8001\u6b40\u8001\u6b43\u8001\u6b63"+
"\u8001\u6b77\u8001\u6b7d\u8001\u6b8f\u8001\u6e40\u8001\u6e7f\u8001\u6f00"+
"\u8001\u6f4a\u8001\u6f50\u8001\u6f50\u8001\u6f93\u8001\u6f9f\u8001\u6fe0"+
"\u8001\u6fe1\u8001\u6fe3\u8001\u6fe3\u8001\u7000\u8001\u87f7\u8001\u8800"+
"\u8001\u8cd5\u8001\u8d00\u8001\u8d08\u8001\uaff0\u8001\uaff3\u8001\uaff5"+
"\u8001\uaffb\u8001\uaffd\u8001\uaffe\u8001\ub000\u8001\ub122\u8001\ub132"+
"\u8001\ub132\u8001\ub150\u8001\ub152\u8001\ub155\u8001\ub155\u8001\ub164"+
"\u8001\ub167\u8001\ub170\u8001\ub2fb\u8001\ubc00\u8001\ubc6a\u8001\ubc70"+
"\u8001\ubc7c\u8001\ubc80\u8001\ubc88\u8001\ubc90\u8001\ubc99\u8001\ud400"+
"\u8001\ud454\u8001\ud456\u8001\ud49c\u8001\ud49e\u8001\ud49f\u8001\ud4a2"+
"\u8001\ud4a2\u8001\ud4a5\u8001\ud4a6\u8001\ud4a9\u8001\ud4ac\u8001\ud4ae"+
"\u8001\ud4b9\u8001\ud4bb\u8001\ud4bb\u8001\ud4bd\u8001\ud4c3\u8001\ud4c5"+
"\u8001\ud505\u8001\ud507\u8001\ud50a\u8001\ud50d\u8001\ud514\u8001\ud516"+
"\u8001\ud51c\u8001\ud51e\u8001\ud539\u8001\ud53b\u8001\ud53e\u8001\ud540"+
"\u8001\ud544\u8001\ud546\u8001\ud546\u8001\ud54a\u8001\ud550\u8001\ud552"+
"\u8001\ud6a5\u8001\ud6a8\u8001\ud6c0\u8001\ud6c2\u8001\ud6da\u8001\ud6dc"+
"\u8001\ud6fa\u8001\ud6fc\u8001\ud714\u8001\ud716\u8001\ud734\u8001\ud736"+
"\u8001\ud74e\u8001\ud750\u8001\ud76e\u8001\ud770\u8001\ud788\u8001\ud78a"+
"\u8001\ud7a8\u8001\ud7aa\u8001\ud7c2\u8001\ud7c4\u8001\ud7cb\u8001\udf00"+
"\u8001\udf1e\u8001\udf25\u8001\udf2a\u8001\ue030\u8001\ue06d\u8001\ue100"+
"\u8001\ue12c\u8001\ue137\u8001\ue13d\u8001\ue14e\u8001\ue14e\u8001\ue290"+
"\u8001\ue2ad\u8001\ue2c0\u8001\ue2eb\u8001\ue4d0\u8001\ue4eb\u8001\ue7e0"+
"\u8001\ue7e6\u8001\ue7e8\u8001\ue7eb\u8001\ue7ed\u8001\ue7ee\u8001\ue7f0"+
"\u8001\ue7fe\u8001\ue800\u8001\ue8c4\u8001\ue900\u8001\ue943\u8001\ue94b"+
"\u8001\ue94b\u8001\uee00\u8001\uee03\u8001\uee05\u8001\uee1f\u8001\uee21"+
"\u8001\uee22\u8001\uee24\u8001\uee24\u8001\uee27\u8001\uee27\u8001\uee29"+
"\u8001\uee32\u8001\uee34\u8001\uee37\u8001\uee39\u8001\uee39\u8001\uee3b"+
"\u8001\uee3b\u8001\uee42\u8001\uee42\u8001\uee47\u8001\uee47\u8001\uee49"+
"\u8001\uee49\u8001\uee4b\u8001\uee4b\u8001\uee4d\u8001\uee4f\u8001\uee51"+
"\u8001\uee52\u8001\uee54\u8001\uee54\u8001\uee57\u8001\uee57\u8001\uee59"+
"\u8001\uee59\u8001\uee5b\u8001\uee5b\u8001\uee5d\u8001\uee5d\u8001\uee5f"+
"\u8001\uee5f\u8001\uee61\u8001\uee62\u8001\uee64\u8001\uee64\u8001\uee67"+
"\u8001\uee6a\u8001\uee6c\u8001\uee72\u8001\uee74\u8001\uee77\u8001\uee79"+
"\u8001\uee7c\u8001\uee7e\u8001\uee7e\u8001\uee80\u8001\uee89\u8001\uee8b"+
"\u8001\uee9b\u8001\ueea1\u8001\ueea3\u8001\ueea5\u8001\ueea9\u8001\ueeab"+
"\u8001\ueebb\u8002\u0000\u8002\ua6df\u8002\ua700\u8002\ub739\u8002\ub740"+
"\u8002\ub81d\u8002\ub820\u8002\ucea1\u8002\uceb0\u8002\uebe0\u8002\uf800"+
"\u8002\ufa1d\u8003\u0000\u8003\u134a\u8003\u1350\u8003\u23af\u0002\u0000"+
"\n\n``\u01e6\u0000\u0002\u0001\u0000\u0000\u0000\u0000\u0006\u0001\u0000"+
"\u0000\u0000\u0000\b\u0001\u0000\u0000\u0000\u0000\n\u0001\u0000\u0000"+
"\u0000\u0000\f\u0001\u0000\u0000\u0000\u0000\u000e\u0001\u0000\u0000\u0000"+
"\u0000\u0010\u0001\u0000\u0000\u0000\u0000\u0012\u0001\u0000\u0000\u0000"+
"\u0000\u0014\u0001\u0000\u0000\u0000\u0000\u0016\u0001\u0000\u0000\u0000"+
"\u0000\u0018\u0001\u0000\u0000\u0000\u0000\u001a\u0001\u0000\u0000\u0000"+
"\u0000\u001c\u0001\u0000\u0000\u0000\u0000\u001e\u0001\u0000\u0000\u0000"+
"\u0000 \u0001\u0000\u0000\u0000\u0000\"\u0001\u0000\u0000\u0000\u0000"+
"$\u0001\u0000\u0000\u0000\u0000&\u0001\u0000\u0000\u0000\u0000(\u0001"+
"\u0000\u0000\u0000\u0000*\u0001\u0000\u0000\u0000\u0000,\u0001\u0000\u0000"+
"\u0000\u0000.\u0001\u0000\u0000\u0000\u00000\u0001\u0000\u0000\u0000\u0000"+
"2\u0001\u0000\u0000\u0000\u00004\u0001\u0000\u0000\u0000\u00006\u0001"+
"\u0000\u0000\u0000\u00008\u0001\u0000\u0000\u0000\u0000:\u0001\u0000\u0000"+
"\u0000\u0000<\u0001\u0000\u0000\u0000\u0000>\u0001\u0000\u0000\u0000\u0000"+
"@\u0001\u0000\u0000\u0000\u0000B\u0001\u0000\u0000\u0000\u0000D\u0001"+
"\u0000\u0000\u0000\u0000F\u0001\u0000\u0000\u0000\u0000H\u0001\u0000\u0000"+
"\u0000\u0000J\u0001\u0000\u0000\u0000\u0000L\u0001\u0000\u0000\u0000\u0000"+
"N\u0001\u0000\u0000\u0000\u0000P\u0001\u0000\u0000\u0000\u0000R\u0001"+
"\u0000\u0000\u0000\u0000T\u0001\u0000\u0000\u0000\u0000V\u0001\u0000\u0000"+
"\u0000\u0000X\u0001\u0000\u0000\u0000\u0000Z\u0001\u0000\u0000\u0000\u0000"+
"\\\u0001\u0000\u0000\u0000\u0000^\u0001\u0000\u0000\u0000\u0000`\u0001"+
"\u0000\u0000\u0000\u0000b\u0001\u0000\u0000\u0000\u0000d\u0001\u0000\u0000"+
"\u0000\u0000f\u0001\u0000\u0000\u0000\u0000h\u0001\u0000\u0000\u0000\u0000"+
"j\u0001\u0000\u0000\u0000\u0000l\u0001\u0000\u0000\u0000\u0000n\u0001"+
"\u0000\u0000\u0000\u0000p\u0001\u0000\u0000\u0000\u0000r\u0001\u0000\u0000"+
"\u0000\u0000t\u0001\u0000\u0000\u0000\u0000v\u0001\u0000\u0000\u0000\u0000"+
"x\u0001\u0000\u0000\u0000\u0000z\u0001\u0000\u0000\u0000\u0001\u008c\u0001"+
"\u0000\u0000\u0000\u0001\u008e\u0001\u0000\u0000\u0000\u0001\u0090\u0001"+
"\u0000\u0000\u0000\u0001\u0092\u0001\u0000\u0000\u0000\u0002\u0094\u0001"+
"\u0000\u0000\u0000\u0004\u0099\u0001\u0000\u0000\u0000\u0006\u009c\u0001"+
"\u0000\u0000\u0000\b\u00a2\u0001\u0000\u0000\u0000\n\u00a5\u0001\u0000"+
"\u0000\u0000\f\u00a7\u0001\u0000\u0000\u0000\u000e\u00aa\u0001\u0000\u0000"+
"\u0000\u0010\u00ac\u0001\u0000\u0000\u0000\u0012\u00ae\u0001\u0000\u0000"+
"\u0000\u0014\u00b0\u0001\u0000\u0000\u0000\u0016\u00b2\u0001\u0000\u0000"+
"\u0000\u0018\u00b4\u0001\u0000\u0000\u0000\u001a\u00b6\u0001\u0000\u0000"+
"\u0000\u001c\u00b8\u0001\u0000\u0000\u0000\u001e\u00ba\u0001\u0000\u0000"+
"\u0000 \u00bc\u0001\u0000\u0000\u0000\"\u00be\u0001\u0000\u0000\u0000"+
"$\u00c0\u0001\u0000\u0000\u0000&\u00c2\u0001\u0000\u0000\u0000(\u00c4"+
"\u0001\u0000\u0000\u0000*\u00c7\u0001\u0000\u0000\u0000,\u00c9\u0001\u0000"+
"\u0000\u0000.\u00cc\u0001\u0000\u0000\u00000\u00cf\u0001\u0000\u0000\u0000"+
"2\u00d1\u0001\u0000\u0000\u00004\u00d4\u0001\u0000\u0000\u00006\u00d6"+
"\u0001\u0000\u0000\u00008\u00d9\u0001\u0000\u0000\u0000:\u00db\u0001\u0000"+
"\u0000\u0000<\u00de\u0001\u0000\u0000\u0000>\u00e1\u0001\u0000\u0000\u0000"+
"@\u00e4\u0001\u0000\u0000\u0000B\u00e7\u0001\u0000\u0000\u0000D\u00e9"+
"\u0001\u0000\u0000\u0000F\u00ec\u0001\u0000\u0000\u0000H\u00ef\u0001\u0000"+
"\u0000\u0000J\u00f1\u0001\u0000\u0000\u0000L\u00f4\u0001\u0000\u0000\u0000"+
"N\u00f6\u0001\u0000\u0000\u0000P\u00fb\u0001\u0000\u0000\u0000R\u0100"+
"\u0001\u0000\u0000\u0000T\u0104\u0001\u0000\u0000\u0000V\u0107\u0001\u0000"+
"\u0000\u0000X\u010b\u0001\u0000\u0000\u0000Z\u0110\u0001\u0000\u0000\u0000"+
"\\\u0116\u0001\u0000\u0000\u0000^\u011a\u0001\u0000\u0000\u0000`\u011f"+
"\u0001\u0000\u0000\u0000b\u0121\u0001\u0000\u0000\u0000d\u0129\u0001\u0000"+
"\u0000\u0000f\u012c\u0001\u0000\u0000\u0000h\u012f\u0001\u0000\u0000\u0000"+
"j\u0132\u0001\u0000\u0000\u0000l\u0135\u0001\u0000\u0000\u0000n\u0138"+
"\u0001\u0000\u0000\u0000p\u013d\u0001\u0000\u0000\u0000r\u0174\u0001\u0000"+
"\u0000\u0000t\u0177\u0001\u0000\u0000\u0000v\u0180\u0001\u0000\u0000\u0000"+
"x\u0182\u0001\u0000\u0000\u0000z\u018d\u0001\u0000\u0000\u0000|\u0198"+
"\u0001\u0000\u0000\u0000~\u019a\u0001\u0000\u0000\u0000\u0080\u019c\u0001"+
"\u0000\u0000\u0000\u0082\u01b6\u0001\u0000\u0000\u0000\u0084\u01b8\u0001"+
"\u0000\u0000\u0000\u0086\u01ba\u0001\u0000\u0000\u0000\u0088\u01bd\u0001"+
"\u0000\u0000\u0000\u008a\u01bf\u0001\u0000\u0000\u0000\u008c\u01c1\u0001"+
"\u0000\u0000\u0000\u008e\u01c4\u0001\u0000\u0000\u0000\u0090\u01cb\u0001"+
"\u0000\u0000\u0000\u0092\u01cd\u0001\u0000\u0000\u0000\u0094\u0095\u0005"+
";\u0000\u0000\u0095\u0003\u0001\u0000\u0000\u0000\u0096\u0097\u0005\r"+
"\u0000\u0000\u0097\u009a\u0005\n\u0000\u0000\u0098\u009a\u0007\u0000\u0000"+
"\u0000\u0099\u0096\u0001\u0000\u0000\u0000\u0099\u0098\u0001\u0000\u0000"+
"\u0000\u009a\u0005\u0001\u0000\u0000\u0000\u009b\u009d\u0007\u0001\u0000"+
"\u0000\u009c\u009b\u0001\u0000\u0000\u0000\u009d\u009e\u0001\u0000\u0000"+
"\u0000\u009e\u009c\u0001\u0000\u0000\u0000\u009e\u009f\u0001\u0000\u0000"+
"\u0000\u009f\u00a0\u0001\u0000\u0000\u0000\u00a0\u00a1\u0006\u0002\u0000"+
"\u0000\u00a1\u0007\u0001\u0000\u0000\u0000\u00a2\u00a3\u0005+\u0000\u0000"+
"\u00a3\u00a4\u0005+\u0000\u0000\u00a4\t\u0001\u0000\u0000\u0000\u00a5"+
"\u00a6\u0005+\u0000\u0000\u00a6\u000b\u0001\u0000\u0000\u0000\u00a7\u00a8"+
"\u0005-\u0000\u0000\u00a8\u00a9\u0005-\u0000\u0000\u00a9\r\u0001\u0000"+
"\u0000\u0000\u00aa\u00ab\u0005-\u0000\u0000\u00ab\u000f\u0001\u0000\u0000"+
"\u0000\u00ac\u00ad\u0005:\u0000\u0000\u00ad\u0011\u0001\u0000\u0000\u0000"+
"\u00ae\u00af\u0005.\u0000\u0000\u00af\u0013\u0001\u0000\u0000\u0000\u00b0"+
"\u00b1\u0005,\u0000\u0000\u00b1\u0015\u0001\u0000\u0000\u0000\u00b2\u00b3"+
"\u0005*\u0000\u0000\u00b3\u0017\u0001\u0000\u0000\u0000\u00b4\u00b5\u0005"+
"/\u0000\u0000\u00b5\u0019\u0001\u0000\u0000\u0000\u00b6\u00b7\u0005%\u0000"+
"\u0000\u00b7\u001b\u0001\u0000\u0000\u0000\u00b8\u00b9\u0005(\u0000\u0000"+
"\u00b9\u001d\u0001\u0000\u0000\u0000\u00ba\u00bb\u0005)\u0000\u0000\u00bb"+
"\u001f\u0001\u0000\u0000\u0000\u00bc\u00bd\u0005[\u0000\u0000\u00bd!\u0001"+
"\u0000\u0000\u0000\u00be\u00bf\u0005]\u0000\u0000\u00bf#\u0001\u0000\u0000"+
"\u0000\u00c0\u00c1\u0005#\u0000\u0000\u00c1%\u0001\u0000\u0000\u0000\u00c2"+
"\u00c3\u0005@\u0000\u0000\u00c3\'\u0001\u0000\u0000\u0000\u00c4\u00c5"+
"\u0005^\u0000\u0000\u00c5\u00c6\u0005[\u0000\u0000\u00c6)\u0001\u0000"+
"\u0000\u0000\u00c7\u00c8\u0005^\u0000\u0000\u00c8+\u0001\u0000\u0000\u0000"+
"\u00c9\u00ca\u0005!\u0000\u0000\u00ca\u00cb\u0005=\u0000\u0000\u00cb-"+
"\u0001\u0000\u0000\u0000\u00cc\u00cd\u0005!\u0000\u0000\u00cd\u00ce\u0005"+
"[\u0000\u0000\u00ce/\u0001\u0000\u0000\u0000\u00cf\u00d0\u0005!\u0000"+
"\u0000\u00d01\u0001\u0000\u0000\u0000\u00d1\u00d2\u0005=\u0000\u0000\u00d2"+
"\u00d3\u0005=\u0000\u0000\u00d33\u0001\u0000\u0000\u0000\u00d4\u00d5\u0005"+
"=\u0000\u0000\u00d55\u0001\u0000\u0000\u0000\u00d6\u00d7\u0005&\u0000"+
"\u0000\u00d7\u00d8\u0005&\u0000\u0000\u00d87\u0001\u0000\u0000\u0000\u00d9"+
"\u00da\u0005&\u0000\u0000\u00da9\u0001\u0000\u0000\u0000\u00db\u00dc\u0005"+
"|\u0000\u0000\u00dc\u00dd\u0005|\u0000\u0000\u00dd;\u0001\u0000\u0000"+
"\u0000\u00de\u00df\u0005?\u0000\u0000\u00df\u00e0\u0005[\u0000\u0000\u00e0"+
"=\u0001\u0000\u0000\u0000\u00e1\u00e2\u0005?\u0000\u0000\u00e2\u00e3\u0005"+
":\u0000\u0000\u00e3?\u0001\u0000\u0000\u0000\u00e4\u00e5\u0005?\u0000"+
"\u0000\u00e5\u00e6\u0005.\u0000\u0000\u00e6A\u0001\u0000\u0000\u0000\u00e7"+
"\u00e8\u0005?\u0000\u0000\u00e8C\u0001\u0000\u0000\u0000\u00e9\u00ea\u0005"+
"$\u0000\u0000\u00ea\u00eb\u0005[\u0000\u0000\u00ebE\u0001\u0000\u0000"+
"\u0000\u00ec\u00ed\u0005>\u0000\u0000\u00ed\u00ee\u0005=\u0000\u0000\u00ee"+
"G\u0001\u0000\u0000\u0000\u00ef\u00f0\u0005>\u0000\u0000\u00f0I\u0001"+
"\u0000\u0000\u0000\u00f1\u00f2\u0005<\u0000\u0000\u00f2\u00f3\u0005=\u0000"+
"\u0000\u00f3K\u0001\u0000\u0000\u0000\u00f4\u00f5\u0005<\u0000\u0000\u00f5"+
"M\u0001\u0000\u0000\u0000\u00f6\u00f7\u0005{\u0000\u0000\u00f7\u00f8\u0006"+
"&\u0001\u0000\u00f8\u00f9\u0001\u0000\u0000\u0000\u00f9\u00fa\u0006&\u0002"+
"\u0000\u00faO\u0001\u0000\u0000\u0000\u00fb\u00fc\u0005}\u0000\u0000\u00fc"+
"\u00fd\u0006\'\u0003\u0000\u00fd\u00fe\u0001\u0000\u0000\u0000\u00fe\u00ff"+
"\u0006\'\u0004\u0000\u00ffQ\u0001\u0000\u0000\u0000\u0100\u0101\u0005"+
"`\u0000\u0000\u0101\u0102\u0001\u0000\u0000\u0000\u0102\u0103\u0006(\u0005"+
"\u0000\u0103S\u0001\u0000\u0000\u0000\u0104\u0105\u0005o\u0000\u0000\u0105"+
"\u0106\u0005r\u0000\u0000\u0106U\u0001\u0000\u0000\u0000\u0107\u0108\u0005"+
"a\u0000\u0000\u0108\u0109\u0005n\u0000\u0000\u0109\u010a\u0005d\u0000"+
"\u0000\u010aW\u0001\u0000\u0000\u0000\u010b\u010c\u0005t\u0000\u0000\u010c"+
"\u010d\u0005r\u0000\u0000\u010d\u010e\u0005u\u0000\u0000\u010e\u010f\u0005"+
"e\u0000\u0000\u010fY\u0001\u0000\u0000\u0000\u0110\u0111\u0005f\u0000"+
"\u0000\u0111\u0112\u0005a\u0000\u0000\u0112\u0113\u0005l\u0000\u0000\u0113"+
"\u0114\u0005s\u0000\u0000\u0114\u0115\u0005e\u0000\u0000\u0115[\u0001"+
"\u0000\u0000\u0000\u0116\u0117\u0005n\u0000\u0000\u0117\u0118\u0005e\u0000"+
"\u0000\u0118\u0119\u0005w\u0000\u0000\u0119]\u0001\u0000\u0000\u0000\u011a"+
"\u011b\u0005n\u0000\u0000\u011b\u011c\u0005u\u0000\u0000\u011c\u011d\u0005"+
"l\u0000\u0000\u011d\u011e\u0005l\u0000\u0000\u011e_\u0001\u0000\u0000"+
"\u0000\u011f\u0120\u0005T\u0000\u0000\u0120a\u0001\u0000\u0000\u0000\u0121"+
"\u0122\u0005m\u0000\u0000\u0122\u0123\u0005a\u0000\u0000\u0123\u0124\u0005"+
"t\u0000\u0000\u0124\u0125\u0005c\u0000\u0000\u0125\u0126\u0005h\u0000"+
"\u0000\u0126\u0127\u0005e\u0000\u0000\u0127\u0128\u0005s\u0000\u0000\u0128"+
"c\u0001\u0000\u0000\u0000\u0129\u012a\u0005g\u0000\u0000\u012a\u012b\u0005"+
"t\u0000\u0000\u012be\u0001\u0000\u0000\u0000\u012c\u012d\u0005g\u0000"+
"\u0000\u012d\u012e\u0005e\u0000\u0000\u012eg\u0001\u0000\u0000\u0000\u012f"+
"\u0130\u0005l\u0000\u0000\u0130\u0131\u0005e\u0000\u0000\u0131i\u0001"+
"\u0000\u0000\u0000\u0132\u0133\u0005l\u0000\u0000\u0133\u0134\u0005t\u0000"+
"\u0000\u0134k\u0001\u0000\u0000\u0000\u0135\u0136\u0005e\u0000\u0000\u0136"+
"\u0137\u0005q\u0000\u0000\u0137m\u0001\u0000\u0000\u0000\u0138\u0139\u0005"+
"n\u0000\u0000\u0139\u013a\u0005e\u0000\u0000\u013ao\u0001\u0000\u0000"+
"\u0000\u013b\u013e\u0003\u0088C\u0000\u013c\u013e\u0005_\u0000\u0000\u013d"+
"\u013b\u0001\u0000\u0000\u0000\u013d\u013c\u0001\u0000\u0000\u0000\u013e"+
"\u0144\u0001\u0000\u0000\u0000\u013f\u0143\u0003\u0088C\u0000\u0140\u0143"+
"\u0003\u008aD\u0000\u0141\u0143\u0007\u0002\u0000\u0000\u0142\u013f\u0001"+
"\u0000\u0000\u0000\u0142\u0140\u0001\u0000\u0000\u0000\u0142\u0141\u0001"+
"\u0000\u0000\u0000\u0143\u0146\u0001\u0000\u0000\u0000\u0144\u0142\u0001"+
"\u0000\u0000\u0000\u0144\u0145\u0001\u0000\u0000\u0000\u0145q\u0001\u0000"+
"\u0000\u0000\u0146\u0144\u0001\u0000\u0000\u0000\u0147\u0149\u0005.\u0000"+
"\u0000\u0148\u014a\u0003\u0080?\u0000\u0149\u0148\u0001\u0000\u0000\u0000"+
"\u014a\u014b\u0001\u0000\u0000\u0000\u014b\u0149\u0001\u0000\u0000\u0000"+
"\u014b\u014c\u0001\u0000\u0000\u0000\u014c\u014e\u0001\u0000\u0000\u0000"+
"\u014d\u014f\u0003\u0082@\u0000\u014e\u014d\u0001\u0000\u0000\u0000\u014e"+
"\u014f\u0001\u0000\u0000\u0000\u014f\u0151\u0001\u0000\u0000\u0000\u0150"+
"\u0152\u0003\u0086B\u0000\u0151\u0150\u0001\u0000\u0000\u0000\u0151\u0152"+
"\u0001\u0000\u0000\u0000\u0152\u0175\u0001\u0000\u0000\u0000\u0153\u0155"+
"\u0003\u0080?\u0000\u0154\u0153\u0001\u0000\u0000\u0000\u0155\u0156\u0001"+
"\u0000\u0000\u0000\u0156\u0154\u0001\u0000\u0000\u0000\u0156\u0157\u0001"+
"\u0000\u0000\u0000\u0157\u0158\u0001\u0000\u0000\u0000\u0158\u015a\u0005"+
".\u0000\u0000\u0159\u015b\u0003\u0080?\u0000\u015a\u0159\u0001\u0000\u0000"+
"\u0000\u015b\u015c\u0001\u0000\u0000\u0000\u015c\u015a\u0001\u0000\u0000"+
"\u0000\u015c\u015d\u0001\u0000\u0000\u0000\u015d\u015f\u0001\u0000\u0000"+
"\u0000\u015e\u0160\u0003\u0082@\u0000\u015f\u015e\u0001\u0000\u0000\u0000"+
"\u015f\u0160\u0001\u0000\u0000\u0000\u0160\u0162\u0001\u0000\u0000\u0000"+
"\u0161\u0163\u0003\u0086B\u0000\u0162\u0161\u0001\u0000\u0000\u0000\u0162"+
"\u0163\u0001\u0000\u0000\u0000\u0163\u0175\u0001\u0000\u0000\u0000\u0164"+
"\u0166\u0003\u0080?\u0000\u0165\u0164\u0001\u0000\u0000\u0000\u0166\u0167"+
"\u0001\u0000\u0000\u0000\u0167\u0165\u0001\u0000\u0000\u0000\u0167\u0168"+
"\u0001\u0000\u0000\u0000\u0168\u0169\u0001\u0000\u0000\u0000\u0169\u016b"+
"\u0003\u0082@\u0000\u016a\u016c\u0003\u0086B\u0000\u016b\u016a\u0001\u0000"+
"\u0000\u0000\u016b\u016c\u0001\u0000\u0000\u0000\u016c\u0175\u0001\u0000"+
"\u0000\u0000\u016d\u016f\u0003\u0080?\u0000\u016e\u016d\u0001\u0000\u0000"+
"\u0000\u016f\u0170\u0001\u0000\u0000\u0000\u0170\u016e\u0001\u0000\u0000"+
"\u0000\u0170\u0171\u0001\u0000\u0000\u0000\u0171\u0172\u0001\u0000\u0000"+
"\u0000\u0172\u0173\u0003\u0086B\u0000\u0173\u0175\u0001\u0000\u0000\u0000"+
"\u0174\u0147\u0001\u0000\u0000\u0000\u0174\u0154\u0001\u0000\u0000\u0000"+
"\u0174\u0165\u0001\u0000\u0000\u0000\u0174\u016e\u0001\u0000\u0000\u0000"+
"\u0175s\u0001\u0000\u0000\u0000\u0176\u0178\u0003\u0080?\u0000\u0177\u0176"+
"\u0001\u0000\u0000\u0000\u0178\u0179\u0001\u0000\u0000\u0000\u0179\u0177"+
"\u0001\u0000\u0000\u0000\u0179\u017a\u0001\u0000\u0000\u0000\u017a\u017c"+
"\u0001\u0000\u0000\u0000\u017b\u017d\u0003|=\u0000\u017c\u017b\u0001\u0000"+
"\u0000\u0000\u017c\u017d\u0001\u0000\u0000\u0000\u017du\u0001\u0000\u0000"+
"\u0000\u017e\u0181\u0003x;\u0000\u017f\u0181\u0003z<\u0000\u0180\u017e"+
"\u0001\u0000\u0000\u0000\u0180\u017f\u0001\u0000\u0000\u0000\u0181w\u0001"+
"\u0000\u0000\u0000\u0182\u0188\u0005\'\u0000\u0000\u0183\u0184\u0005\'"+
"\u0000\u0000\u0184\u0187\u0005\'\u0000\u0000\u0185\u0187\b\u0003\u0000"+
"\u0000\u0186\u0183\u0001\u0000\u0000\u0000\u0186\u0185\u0001\u0000\u0000"+
"\u0000\u0187\u018a\u0001\u0000\u0000\u0000\u0188\u0186\u0001\u0000\u0000"+
"\u0000\u0188\u0189\u0001\u0000\u0000\u0000\u0189\u018b\u0001\u0000\u0000"+
"\u0000\u018a\u0188\u0001\u0000\u0000\u0000\u018b\u018c\u0005\'\u0000\u0000"+
"\u018cy\u0001\u0000\u0000\u0000\u018d\u0193\u0005\"\u0000\u0000\u018e"+
"\u018f\u0005\"\u0000\u0000\u018f\u0192\u0005\"\u0000\u0000\u0190\u0192"+
"\b\u0004\u0000\u0000\u0191\u018e\u0001\u0000\u0000\u0000\u0191\u0190\u0001"+
"\u0000\u0000\u0000\u0192\u0195\u0001\u0000\u0000\u0000\u0193\u0191\u0001"+
"\u0000\u0000\u0000\u0193\u0194\u0001\u0000\u0000\u0000\u0194\u0196\u0001"+
"\u0000\u0000\u0000\u0195\u0193\u0001\u0000\u0000\u0000\u0196\u0197\u0005"+
"\"\u0000\u0000\u0197{\u0001\u0000\u0000\u0000\u0198\u0199\u0007\u0005"+
"\u0000\u0000\u0199}\u0001\u0000\u0000\u0000\u019a\u019b\u0007\u0006\u0000"+
"\u0000\u019b\u007f\u0001\u0000\u0000\u0000\u019c\u019d\u0007\u0007\u0000"+
"\u0000\u019d\u0081\u0001\u0000\u0000\u0000\u019e\u01a2\u0005e\u0000\u0000"+
"\u019f\u01a1\u0003\u0084A\u0000\u01a0\u019f\u0001\u0000\u0000\u0000\u01a1"+
"\u01a4\u0001\u0000\u0000\u0000\u01a2\u01a0\u0001\u0000\u0000\u0000\u01a2"+
"\u01a3\u0001\u0000\u0000\u0000\u01a3\u01a6\u0001\u0000\u0000\u0000\u01a4"+
"\u01a2\u0001\u0000\u0000\u0000\u01a5\u01a7\u0003\u0080?\u0000\u01a6\u01a5"+
"\u0001\u0000\u0000\u0000\u01a7\u01a8\u0001\u0000\u0000\u0000\u01a8\u01a6"+
"\u0001\u0000\u0000\u0000\u01a8\u01a9\u0001\u0000\u0000\u0000\u01a9\u01b7"+
"\u0001\u0000\u0000\u0000\u01aa\u01ae\u0005E\u0000\u0000\u01ab\u01ad\u0003"+
"\u0084A\u0000\u01ac\u01ab\u0001\u0000\u0000\u0000\u01ad\u01b0\u0001\u0000"+
"\u0000\u0000\u01ae\u01ac\u0001\u0000\u0000\u0000\u01ae\u01af\u0001\u0000"+
"\u0000\u0000\u01af\u01b2\u0001\u0000\u0000\u0000\u01b0\u01ae\u0001\u0000"+
"\u0000\u0000\u01b1\u01b3\u0003\u0080?\u0000\u01b2\u01b1\u0001\u0000\u0000"+
"\u0000\u01b3\u01b4\u0001\u0000\u0000\u0000\u01b4\u01b2\u0001\u0000\u0000"+
"\u0000\u01b4\u01b5\u0001\u0000\u0000\u0000\u01b5\u01b7\u0001\u0000\u0000"+
"\u0000\u01b6\u019e\u0001\u0000\u0000\u0000\u01b6\u01aa\u0001\u0000\u0000"+
"\u0000\u01b7\u0083\u0001\u0000\u0000\u0000\u01b8\u01b9\u0007\b\u0000\u0000"+
"\u01b9\u0085\u0001\u0000\u0000\u0000\u01ba\u01bb\u0007\t\u0000\u0000\u01bb"+
"\u0087\u0001\u0000\u0000\u0000\u01bc\u01be\u0007\n\u0000\u0000\u01bd\u01bc"+
"\u0001\u0000\u0000\u0000\u01be\u0089\u0001\u0000\u0000\u0000\u01bf\u01c0"+
"\u0007\u0007\u0000\u0000\u01c0\u008b\u0001\u0000\u0000\u0000\u01c1\u01c2"+
"\u0005`\u0000\u0000\u01c2\u01c3\u0005`\u0000\u0000\u01c3\u008d\u0001\u0000"+
"\u0000\u0000\u01c4\u01c5\u0005#\u0000\u0000\u01c5\u01c6\u0005{\u0000\u0000"+
"\u01c6\u01c7\u0001\u0000\u0000\u0000\u01c7\u01c8\u0006F\u0006\u0000\u01c8"+
"\u01c9\u0001\u0000\u0000\u0000\u01c9\u01ca\u0006F\u0002\u0000\u01ca\u008f"+
"\u0001\u0000\u0000\u0000\u01cb\u01cc\b\u000b\u0000\u0000\u01cc\u0091\u0001"+
"\u0000\u0000\u0000\u01cd\u01ce\u0005`\u0000\u0000\u01ce\u01cf\u0001\u0000"+
"\u0000\u0000\u01cf\u01d0\u0006H\u0007\u0000\u01d0\u01d1\u0006H\u0004\u0000"+
"\u01d1\u0093\u0001\u0000\u0000\u0000\u001f\u0000\u0001\u0099\u009e\u013d"+
"\u0142\u0144\u014b\u014e\u0151\u0156\u015c\u015f\u0162\u0167\u016b\u0170"+
"\u0174\u0179\u017c\u0180\u0186\u0188\u0191\u0193\u01a2\u01a8\u01ae\u01b4"+
"\u01b6\u01bd\b\u0000\u0001\u0000\u0001&\u0000\u0005\u0000\u0000\u0001"+
"\'\u0001\u0004\u0000\u0000\u0005\u0001\u0000\u0001F\u0002\u0007(\u0000";
"H\u0007H\u0002I\u0007I\u0001\u0000\u0001\u0000\u0001\u0001\u0001\u0001"+
"\u0001\u0001\u0003\u0001\u009c\b\u0001\u0001\u0002\u0004\u0002\u009f\b"+
"\u0002\u000b\u0002\f\u0002\u00a0\u0001\u0002\u0001\u0002\u0001\u0003\u0001"+
"\u0003\u0001\u0003\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001"+
"\u0005\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007\u0001\b\u0001\b"+
"\u0001\t\u0001\t\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0001\f\u0001"+
"\f\u0001\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f\u0001"+
"\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001"+
"\u0013\u0001\u0013\u0001\u0013\u0001\u0014\u0001\u0014\u0001\u0015\u0001"+
"\u0015\u0001\u0015\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0017\u0001"+
"\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001"+
"\u001a\u0001\u001a\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001c\u0001"+
"\u001c\u0001\u001c\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001e\u0001"+
"\u001e\u0001\u001e\u0001\u001f\u0001\u001f\u0001\u001f\u0001 \u0001 \u0001"+
"!\u0001!\u0001!\u0001\"\u0001\"\u0001\"\u0001#\u0001#\u0001$\u0001$\u0001"+
"$\u0001%\u0001%\u0001&\u0001&\u0001&\u0001&\u0001&\u0001\'\u0001\'\u0001"+
"\'\u0001\'\u0001\'\u0001(\u0001(\u0001(\u0001(\u0001)\u0001)\u0001)\u0001"+
"*\u0001*\u0001*\u0001*\u0001+\u0001+\u0001+\u0001+\u0001+\u0001,\u0001"+
",\u0001,\u0001,\u0001,\u0001,\u0001-\u0001-\u0001-\u0001-\u0001.\u0001"+
".\u0001.\u0001.\u0001.\u0001/\u0001/\u00010\u00010\u00010\u00010\u0001"+
"0\u00010\u00010\u00010\u00011\u00011\u00011\u00012\u00012\u00012\u0001"+
"3\u00013\u00013\u00014\u00014\u00014\u00015\u00015\u00015\u00016\u0001"+
"6\u00016\u00017\u00017\u00037\u0140\b7\u00017\u00017\u00017\u00057\u0145"+
"\b7\n7\f7\u0148\t7\u00018\u00018\u00048\u014c\b8\u000b8\f8\u014d\u0001"+
"8\u00038\u0151\b8\u00018\u00038\u0154\b8\u00018\u00048\u0157\b8\u000b"+
"8\f8\u0158\u00018\u00018\u00048\u015d\b8\u000b8\f8\u015e\u00018\u0003"+
"8\u0162\b8\u00018\u00038\u0165\b8\u00018\u00048\u0168\b8\u000b8\f8\u0169"+
"\u00018\u00018\u00038\u016e\b8\u00018\u00048\u0171\b8\u000b8\f8\u0172"+
"\u00018\u00018\u00038\u0177\b8\u00019\u00049\u017a\b9\u000b9\f9\u017b"+
"\u00019\u00039\u017f\b9\u0001:\u0001:\u0003:\u0183\b:\u0001;\u0001;\u0001"+
";\u0001;\u0005;\u0189\b;\n;\f;\u018c\t;\u0001;\u0001;\u0001<\u0001<\u0001"+
"<\u0001<\u0005<\u0194\b<\n<\f<\u0197\t<\u0001<\u0001<\u0001=\u0001=\u0001"+
"=\u0001=\u0005=\u019f\b=\n=\f=\u01a2\t=\u0001=\u0001=\u0001>\u0001>\u0001"+
"?\u0001?\u0001@\u0001@\u0001A\u0001A\u0005A\u01ae\bA\nA\fA\u01b1\tA\u0001"+
"A\u0004A\u01b4\bA\u000bA\fA\u01b5\u0001A\u0001A\u0005A\u01ba\bA\nA\fA"+
"\u01bd\tA\u0001A\u0004A\u01c0\bA\u000bA\fA\u01c1\u0003A\u01c4\bA\u0001"+
"B\u0001B\u0001C\u0001C\u0001D\u0003D\u01cb\bD\u0001E\u0001E\u0001F\u0001"+
"F\u0001F\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001H\u0001"+
"H\u0001I\u0001I\u0001I\u0001I\u0001I\u0001\u01a0\u0000J\u0002\u0001\u0004"+
"\u0000\u0006\u0002\b\u0003\n\u0004\f\u0005\u000e\u0006\u0010\u0007\u0012"+
"\b\u0014\t\u0016\n\u0018\u000b\u001a\f\u001c\r\u001e\u000e \u000f\"\u0010"+
"$\u0011&\u0012(\u0013*\u0014,\u0015.\u00160\u00172\u00184\u00196\u001a"+
"8\u001b:\u001c<\u001d>\u001e@\u001fB D!F\"H#J$L%N&P\'R(T)V*X+Z,\\-^.`"+
"/b0d1f2h3j4l5n6p7r8t9v:x;z<|=~\u0000\u0080\u0000\u0082\u0000\u0084\u0000"+
"\u0086\u0000\u0088\u0000\u008a\u0000\u008c\u0000\u008e>\u0090?\u0092@"+
"\u0094\u0000\u0002\u0000\u0001\f\u0003\u0000\n\n\r\r\u2028\u2029\u0003"+
"\u0000\t\n\r\r \u0002\u0000$$__\u0002\u0000\n\n\'\'\u0002\u0000\n\n\""+
"\"\u0002\u0000LLll\u0003\u000009AFaf\u0001\u000009\u0002\u0000++--\u0004"+
"\u0000DDFFddff\u0293\u0000AZaz\u00aa\u00aa\u00b5\u00b5\u00ba\u00ba\u00c0"+
"\u00d6\u00d8\u00f6\u00f8\u02c1\u02c6\u02d1\u02e0\u02e4\u02ec\u02ec\u02ee"+
"\u02ee\u0370\u0374\u0376\u0377\u037a\u037d\u037f\u037f\u0386\u0386\u0388"+
"\u038a\u038c\u038c\u038e\u03a1\u03a3\u03f5\u03f7\u0481\u048a\u052f\u0531"+
"\u0556\u0559\u0559\u0560\u0588\u05d0\u05ea\u05ef\u05f2\u0620\u064a\u066e"+
"\u066f\u0671\u06d3\u06d5\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa\u06fc\u06ff"+
"\u06ff\u0710\u0710\u0712\u072f\u074d\u07a5\u07b1\u07b1\u07ca\u07ea\u07f4"+
"\u07f5\u07fa\u07fa\u0800\u0815\u081a\u081a\u0824\u0824\u0828\u0828\u0840"+
"\u0858\u0860\u086a\u0870\u0887\u0889\u088e\u08a0\u08c9\u0904\u0939\u093d"+
"\u093d\u0950\u0950\u0958\u0961\u0971\u0980\u0985\u098c\u098f\u0990\u0993"+
"\u09a8\u09aa\u09b0\u09b2\u09b2\u09b6\u09b9\u09bd\u09bd\u09ce\u09ce\u09dc"+
"\u09dd\u09df\u09e1\u09f0\u09f1\u09fc\u09fc\u0a05\u0a0a\u0a0f\u0a10\u0a13"+
"\u0a28\u0a2a\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59\u0a5c\u0a5e"+
"\u0a5e\u0a72\u0a74\u0a85\u0a8d\u0a8f\u0a91\u0a93\u0aa8\u0aaa\u0ab0\u0ab2"+
"\u0ab3\u0ab5\u0ab9\u0abd\u0abd\u0ad0\u0ad0\u0ae0\u0ae1\u0af9\u0af9\u0b05"+
"\u0b0c\u0b0f\u0b10\u0b13\u0b28\u0b2a\u0b30\u0b32\u0b33\u0b35\u0b39\u0b3d"+
"\u0b3d\u0b5c\u0b5d\u0b5f\u0b61\u0b71\u0b71\u0b83\u0b83\u0b85\u0b8a\u0b8e"+
"\u0b90\u0b92\u0b95\u0b99\u0b9a\u0b9c\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8"+
"\u0baa\u0bae\u0bb9\u0bd0\u0bd0\u0c05\u0c0c\u0c0e\u0c10\u0c12\u0c28\u0c2a"+
"\u0c39\u0c3d\u0c3d\u0c58\u0c5a\u0c5d\u0c5d\u0c60\u0c61\u0c80\u0c80\u0c85"+
"\u0c8c\u0c8e\u0c90\u0c92\u0ca8\u0caa\u0cb3\u0cb5\u0cb9\u0cbd\u0cbd\u0cdd"+
"\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04\u0d0c\u0d0e\u0d10\u0d12\u0d3a\u0d3d"+
"\u0d3d\u0d4e\u0d4e\u0d54\u0d56\u0d5f\u0d61\u0d7a\u0d7f\u0d85\u0d96\u0d9a"+
"\u0db1\u0db3\u0dbb\u0dbd\u0dbd\u0dc0\u0dc6\u0e01\u0e30\u0e32\u0e33\u0e40"+
"\u0e46\u0e81\u0e82\u0e84\u0e84\u0e86\u0e8a\u0e8c\u0ea3\u0ea5\u0ea5\u0ea7"+
"\u0eb0\u0eb2\u0eb3\u0ebd\u0ebd\u0ec0\u0ec4\u0ec6\u0ec6\u0edc\u0edf\u0f00"+
"\u0f00\u0f40\u0f47\u0f49\u0f6c\u0f88\u0f8c\u1000\u102a\u103f\u103f\u1050"+
"\u1055\u105a\u105d\u1061\u1061\u1065\u1066\u106e\u1070\u1075\u1081\u108e"+
"\u108e\u10a0\u10c5\u10c7\u10c7\u10cd\u10cd\u10d0\u10fa\u10fc\u1248\u124a"+
"\u124d\u1250\u1256\u1258\u1258\u125a\u125d\u1260\u1288\u128a\u128d\u1290"+
"\u12b0\u12b2\u12b5\u12b8\u12be\u12c0\u12c0\u12c2\u12c5\u12c8\u12d6\u12d8"+
"\u1310\u1312\u1315\u1318\u135a\u1380\u138f\u13a0\u13f5\u13f8\u13fd\u1401"+
"\u166c\u166f\u167f\u1681\u169a\u16a0\u16ea\u16f1\u16f8\u1700\u1711\u171f"+
"\u1731\u1740\u1751\u1760\u176c\u176e\u1770\u1780\u17b3\u17d7\u17d7\u17dc"+
"\u17dc\u1820\u1878\u1880\u1884\u1887\u18a8\u18aa\u18aa\u18b0\u18f5\u1900"+
"\u191e\u1950\u196d\u1970\u1974\u1980\u19ab\u19b0\u19c9\u1a00\u1a16\u1a20"+
"\u1a54\u1aa7\u1aa7\u1b05\u1b33\u1b45\u1b4c\u1b83\u1ba0\u1bae\u1baf\u1bba"+
"\u1be5\u1c00\u1c23\u1c4d\u1c4f\u1c5a\u1c7d\u1c80\u1c88\u1c90\u1cba\u1cbd"+
"\u1cbf\u1ce9\u1cec\u1cee\u1cf3\u1cf5\u1cf6\u1cfa\u1cfa\u1d00\u1dbf\u1e00"+
"\u1f15\u1f18\u1f1d\u1f20\u1f45\u1f48\u1f4d\u1f50\u1f57\u1f59\u1f59\u1f5b"+
"\u1f5b\u1f5d\u1f5d\u1f5f\u1f7d\u1f80\u1fb4\u1fb6\u1fbc\u1fbe\u1fbe\u1fc2"+
"\u1fc4\u1fc6\u1fcc\u1fd0\u1fd3\u1fd6\u1fdb\u1fe0\u1fec\u1ff2\u1ff4\u1ff6"+
"\u1ffc\u2071\u2071\u207f\u207f\u2090\u209c\u2102\u2102\u2107\u2107\u210a"+
"\u2113\u2115\u2115\u2119\u211d\u2124\u2124\u2126\u2126\u2128\u2128\u212a"+
"\u212d\u212f\u2139\u213c\u213f\u2145\u2149\u214e\u214e\u2183\u2184\u2c00"+
"\u2ce4\u2ceb\u2cee\u2cf2\u2cf3\u2d00\u2d25\u2d27\u2d27\u2d2d\u2d2d\u2d30"+
"\u2d67\u2d6f\u2d6f\u2d80\u2d96\u2da0\u2da6\u2da8\u2dae\u2db0\u2db6\u2db8"+
"\u2dbe\u2dc0\u2dc6\u2dc8\u2dce\u2dd0\u2dd6\u2dd8\u2dde\u2e2f\u2e2f\u3005"+
"\u3006\u3031\u3035\u303b\u303c\u3041\u3096\u309d\u309f\u30a1\u30fa\u30fc"+
"\u30ff\u3105\u312f\u3131\u318e\u31a0\u31bf\u31f0\u31ff\u3400\u4dbf\u4e00"+
"\u8000\ua48c\u8000\ua4d0\u8000\ua4fd\u8000\ua500\u8000\ua60c\u8000\ua610"+
"\u8000\ua61f\u8000\ua62a\u8000\ua62b\u8000\ua640\u8000\ua66e\u8000\ua67f"+
"\u8000\ua69d\u8000\ua6a0\u8000\ua6e5\u8000\ua717\u8000\ua71f\u8000\ua722"+
"\u8000\ua788\u8000\ua78b\u8000\ua7ca\u8000\ua7d0\u8000\ua7d1\u8000\ua7d3"+
"\u8000\ua7d3\u8000\ua7d5\u8000\ua7d9\u8000\ua7f2\u8000\ua801\u8000\ua803"+
"\u8000\ua805\u8000\ua807\u8000\ua80a\u8000\ua80c\u8000\ua822\u8000\ua840"+
"\u8000\ua873\u8000\ua882\u8000\ua8b3\u8000\ua8f2\u8000\ua8f7\u8000\ua8fb"+
"\u8000\ua8fb\u8000\ua8fd\u8000\ua8fe\u8000\ua90a\u8000\ua925\u8000\ua930"+
"\u8000\ua946\u8000\ua960\u8000\ua97c\u8000\ua984\u8000\ua9b2\u8000\ua9cf"+
"\u8000\ua9cf\u8000\ua9e0\u8000\ua9e4\u8000\ua9e6\u8000\ua9ef\u8000\ua9fa"+
"\u8000\ua9fe\u8000\uaa00\u8000\uaa28\u8000\uaa40\u8000\uaa42\u8000\uaa44"+
"\u8000\uaa4b\u8000\uaa60\u8000\uaa76\u8000\uaa7a\u8000\uaa7a\u8000\uaa7e"+
"\u8000\uaaaf\u8000\uaab1\u8000\uaab1\u8000\uaab5\u8000\uaab6\u8000\uaab9"+
"\u8000\uaabd\u8000\uaac0\u8000\uaac0\u8000\uaac2\u8000\uaac2\u8000\uaadb"+
"\u8000\uaadd\u8000\uaae0\u8000\uaaea\u8000\uaaf2\u8000\uaaf4\u8000\uab01"+
"\u8000\uab06\u8000\uab09\u8000\uab0e\u8000\uab11\u8000\uab16\u8000\uab20"+
"\u8000\uab26\u8000\uab28\u8000\uab2e\u8000\uab30\u8000\uab5a\u8000\uab5c"+
"\u8000\uab69\u8000\uab70\u8000\uabe2\u8000\uac00\u8000\ud7a3\u8000\ud7b0"+
"\u8000\ud7c6\u8000\ud7cb\u8000\ud7fb\u8000\uf900\u8000\ufa6d\u8000\ufa70"+
"\u8000\ufad9\u8000\ufb00\u8000\ufb06\u8000\ufb13\u8000\ufb17\u8000\ufb1d"+
"\u8000\ufb1d\u8000\ufb1f\u8000\ufb28\u8000\ufb2a\u8000\ufb36\u8000\ufb38"+
"\u8000\ufb3c\u8000\ufb3e\u8000\ufb3e\u8000\ufb40\u8000\ufb41\u8000\ufb43"+
"\u8000\ufb44\u8000\ufb46\u8000\ufbb1\u8000\ufbd3\u8000\ufd3d\u8000\ufd50"+
"\u8000\ufd8f\u8000\ufd92\u8000\ufdc7\u8000\ufdf0\u8000\ufdfb\u8000\ufe70"+
"\u8000\ufe74\u8000\ufe76\u8000\ufefc\u8000\uff21\u8000\uff3a\u8000\uff41"+
"\u8000\uff5a\u8000\uff66\u8000\uffbe\u8000\uffc2\u8000\uffc7\u8000\uffca"+
"\u8000\uffcf\u8000\uffd2\u8000\uffd7\u8000\uffda\u8000\uffdc\u8001\u0000"+
"\u8001\u000b\u8001\r\u8001&\u8001(\u8001:\u8001<\u8001=\u8001?\u8001M"+
"\u8001P\u8001]\u8001\u0080\u8001\u00fa\u8001\u0280\u8001\u029c\u8001\u02a0"+
"\u8001\u02d0\u8001\u0300\u8001\u031f\u8001\u032d\u8001\u0340\u8001\u0342"+
"\u8001\u0349\u8001\u0350\u8001\u0375\u8001\u0380\u8001\u039d\u8001\u03a0"+
"\u8001\u03c3\u8001\u03c8\u8001\u03cf\u8001\u0400\u8001\u049d\u8001\u04b0"+
"\u8001\u04d3\u8001\u04d8\u8001\u04fb\u8001\u0500\u8001\u0527\u8001\u0530"+
"\u8001\u0563\u8001\u0570\u8001\u057a\u8001\u057c\u8001\u058a\u8001\u058c"+
"\u8001\u0592\u8001\u0594\u8001\u0595\u8001\u0597\u8001\u05a1\u8001\u05a3"+
"\u8001\u05b1\u8001\u05b3\u8001\u05b9\u8001\u05bb\u8001\u05bc\u8001\u0600"+
"\u8001\u0736\u8001\u0740\u8001\u0755\u8001\u0760\u8001\u0767\u8001\u0780"+
"\u8001\u0785\u8001\u0787\u8001\u07b0\u8001\u07b2\u8001\u07ba\u8001\u0800"+
"\u8001\u0805\u8001\u0808\u8001\u0808\u8001\u080a\u8001\u0835\u8001\u0837"+
"\u8001\u0838\u8001\u083c\u8001\u083c\u8001\u083f\u8001\u0855\u8001\u0860"+
"\u8001\u0876\u8001\u0880\u8001\u089e\u8001\u08e0\u8001\u08f2\u8001\u08f4"+
"\u8001\u08f5\u8001\u0900\u8001\u0915\u8001\u0920\u8001\u0939\u8001\u0980"+
"\u8001\u09b7\u8001\u09be\u8001\u09bf\u8001\u0a00\u8001\u0a00\u8001\u0a10"+
"\u8001\u0a13\u8001\u0a15\u8001\u0a17\u8001\u0a19\u8001\u0a35\u8001\u0a60"+
"\u8001\u0a7c\u8001\u0a80\u8001\u0a9c\u8001\u0ac0\u8001\u0ac7\u8001\u0ac9"+
"\u8001\u0ae4\u8001\u0b00\u8001\u0b35\u8001\u0b40\u8001\u0b55\u8001\u0b60"+
"\u8001\u0b72\u8001\u0b80\u8001\u0b91\u8001\u0c00\u8001\u0c48\u8001\u0c80"+
"\u8001\u0cb2\u8001\u0cc0\u8001\u0cf2\u8001\u0d00\u8001\u0d23\u8001\u0e80"+
"\u8001\u0ea9\u8001\u0eb0\u8001\u0eb1\u8001\u0f00\u8001\u0f1c\u8001\u0f27"+
"\u8001\u0f27\u8001\u0f30\u8001\u0f45\u8001\u0f70\u8001\u0f81\u8001\u0fb0"+
"\u8001\u0fc4\u8001\u0fe0\u8001\u0ff6\u8001\u1003\u8001\u1037\u8001\u1071"+
"\u8001\u1072\u8001\u1075\u8001\u1075\u8001\u1083\u8001\u10af\u8001\u10d0"+
"\u8001\u10e8\u8001\u1103\u8001\u1126\u8001\u1144\u8001\u1144\u8001\u1147"+
"\u8001\u1147\u8001\u1150\u8001\u1172\u8001\u1176\u8001\u1176\u8001\u1183"+
"\u8001\u11b2\u8001\u11c1\u8001\u11c4\u8001\u11da\u8001\u11da\u8001\u11dc"+
"\u8001\u11dc\u8001\u1200\u8001\u1211\u8001\u1213\u8001\u122b\u8001\u123f"+
"\u8001\u1240\u8001\u1280\u8001\u1286\u8001\u1288\u8001\u1288\u8001\u128a"+
"\u8001\u128d\u8001\u128f\u8001\u129d\u8001\u129f\u8001\u12a8\u8001\u12b0"+
"\u8001\u12de\u8001\u1305\u8001\u130c\u8001\u130f\u8001\u1310\u8001\u1313"+
"\u8001\u1328\u8001\u132a\u8001\u1330\u8001\u1332\u8001\u1333\u8001\u1335"+
"\u8001\u1339\u8001\u133d\u8001\u133d\u8001\u1350\u8001\u1350\u8001\u135d"+
"\u8001\u1361\u8001\u1400\u8001\u1434\u8001\u1447\u8001\u144a\u8001\u145f"+
"\u8001\u1461\u8001\u1480\u8001\u14af\u8001\u14c4\u8001\u14c5\u8001\u14c7"+
"\u8001\u14c7\u8001\u1580\u8001\u15ae\u8001\u15d8\u8001\u15db\u8001\u1600"+
"\u8001\u162f\u8001\u1644\u8001\u1644\u8001\u1680\u8001\u16aa\u8001\u16b8"+
"\u8001\u16b8\u8001\u1700\u8001\u171a\u8001\u1740\u8001\u1746\u8001\u1800"+
"\u8001\u182b\u8001\u18a0\u8001\u18df\u8001\u18ff\u8001\u1906\u8001\u1909"+
"\u8001\u1909\u8001\u190c\u8001\u1913\u8001\u1915\u8001\u1916\u8001\u1918"+
"\u8001\u192f\u8001\u193f\u8001\u193f\u8001\u1941\u8001\u1941\u8001\u19a0"+
"\u8001\u19a7\u8001\u19aa\u8001\u19d0\u8001\u19e1\u8001\u19e1\u8001\u19e3"+
"\u8001\u19e3\u8001\u1a00\u8001\u1a00\u8001\u1a0b\u8001\u1a32\u8001\u1a3a"+
"\u8001\u1a3a\u8001\u1a50\u8001\u1a50\u8001\u1a5c\u8001\u1a89\u8001\u1a9d"+
"\u8001\u1a9d\u8001\u1ab0\u8001\u1af8\u8001\u1c00\u8001\u1c08\u8001\u1c0a"+
"\u8001\u1c2e\u8001\u1c40\u8001\u1c40\u8001\u1c72\u8001\u1c8f\u8001\u1d00"+
"\u8001\u1d06\u8001\u1d08\u8001\u1d09\u8001\u1d0b\u8001\u1d30\u8001\u1d46"+
"\u8001\u1d46\u8001\u1d60\u8001\u1d65\u8001\u1d67\u8001\u1d68\u8001\u1d6a"+
"\u8001\u1d89\u8001\u1d98\u8001\u1d98\u8001\u1ee0\u8001\u1ef2\u8001\u1f02"+
"\u8001\u1f02\u8001\u1f04\u8001\u1f10\u8001\u1f12\u8001\u1f33\u8001\u1fb0"+
"\u8001\u1fb0\u8001\u2000\u8001\u2399\u8001\u2480\u8001\u2543\u8001\u2f90"+
"\u8001\u2ff0\u8001\u3000\u8001\u342f\u8001\u3441\u8001\u3446\u8001\u4400"+
"\u8001\u4646\u8001\u6800\u8001\u6a38\u8001\u6a40\u8001\u6a5e\u8001\u6a70"+
"\u8001\u6abe\u8001\u6ad0\u8001\u6aed\u8001\u6b00\u8001\u6b2f\u8001\u6b40"+
"\u8001\u6b43\u8001\u6b63\u8001\u6b77\u8001\u6b7d\u8001\u6b8f\u8001\u6e40"+
"\u8001\u6e7f\u8001\u6f00\u8001\u6f4a\u8001\u6f50\u8001\u6f50\u8001\u6f93"+
"\u8001\u6f9f\u8001\u6fe0\u8001\u6fe1\u8001\u6fe3\u8001\u6fe3\u8001\u7000"+
"\u8001\u87f7\u8001\u8800\u8001\u8cd5\u8001\u8d00\u8001\u8d08\u8001\uaff0"+
"\u8001\uaff3\u8001\uaff5\u8001\uaffb\u8001\uaffd\u8001\uaffe\u8001\ub000"+
"\u8001\ub122\u8001\ub132\u8001\ub132\u8001\ub150\u8001\ub152\u8001\ub155"+
"\u8001\ub155\u8001\ub164\u8001\ub167\u8001\ub170\u8001\ub2fb\u8001\ubc00"+
"\u8001\ubc6a\u8001\ubc70\u8001\ubc7c\u8001\ubc80\u8001\ubc88\u8001\ubc90"+
"\u8001\ubc99\u8001\ud400\u8001\ud454\u8001\ud456\u8001\ud49c\u8001\ud49e"+
"\u8001\ud49f\u8001\ud4a2\u8001\ud4a2\u8001\ud4a5\u8001\ud4a6\u8001\ud4a9"+
"\u8001\ud4ac\u8001\ud4ae\u8001\ud4b9\u8001\ud4bb\u8001\ud4bb\u8001\ud4bd"+
"\u8001\ud4c3\u8001\ud4c5\u8001\ud505\u8001\ud507\u8001\ud50a\u8001\ud50d"+
"\u8001\ud514\u8001\ud516\u8001\ud51c\u8001\ud51e\u8001\ud539\u8001\ud53b"+
"\u8001\ud53e\u8001\ud540\u8001\ud544\u8001\ud546\u8001\ud546\u8001\ud54a"+
"\u8001\ud550\u8001\ud552\u8001\ud6a5\u8001\ud6a8\u8001\ud6c0\u8001\ud6c2"+
"\u8001\ud6da\u8001\ud6dc\u8001\ud6fa\u8001\ud6fc\u8001\ud714\u8001\ud716"+
"\u8001\ud734\u8001\ud736\u8001\ud74e\u8001\ud750\u8001\ud76e\u8001\ud770"+
"\u8001\ud788\u8001\ud78a\u8001\ud7a8\u8001\ud7aa\u8001\ud7c2\u8001\ud7c4"+
"\u8001\ud7cb\u8001\udf00\u8001\udf1e\u8001\udf25\u8001\udf2a\u8001\ue030"+
"\u8001\ue06d\u8001\ue100\u8001\ue12c\u8001\ue137\u8001\ue13d\u8001\ue14e"+
"\u8001\ue14e\u8001\ue290\u8001\ue2ad\u8001\ue2c0\u8001\ue2eb\u8001\ue4d0"+
"\u8001\ue4eb\u8001\ue7e0\u8001\ue7e6\u8001\ue7e8\u8001\ue7eb\u8001\ue7ed"+
"\u8001\ue7ee\u8001\ue7f0\u8001\ue7fe\u8001\ue800\u8001\ue8c4\u8001\ue900"+
"\u8001\ue943\u8001\ue94b\u8001\ue94b\u8001\uee00\u8001\uee03\u8001\uee05"+
"\u8001\uee1f\u8001\uee21\u8001\uee22\u8001\uee24\u8001\uee24\u8001\uee27"+
"\u8001\uee27\u8001\uee29\u8001\uee32\u8001\uee34\u8001\uee37\u8001\uee39"+
"\u8001\uee39\u8001\uee3b\u8001\uee3b\u8001\uee42\u8001\uee42\u8001\uee47"+
"\u8001\uee47\u8001\uee49\u8001\uee49\u8001\uee4b\u8001\uee4b\u8001\uee4d"+
"\u8001\uee4f\u8001\uee51\u8001\uee52\u8001\uee54\u8001\uee54\u8001\uee57"+
"\u8001\uee57\u8001\uee59\u8001\uee59\u8001\uee5b\u8001\uee5b\u8001\uee5d"+
"\u8001\uee5d\u8001\uee5f\u8001\uee5f\u8001\uee61\u8001\uee62\u8001\uee64"+
"\u8001\uee64\u8001\uee67\u8001\uee6a\u8001\uee6c\u8001\uee72\u8001\uee74"+
"\u8001\uee77\u8001\uee79\u8001\uee7c\u8001\uee7e\u8001\uee7e\u8001\uee80"+
"\u8001\uee89\u8001\uee8b\u8001\uee9b\u8001\ueea1\u8001\ueea3\u8001\ueea5"+
"\u8001\ueea9\u8001\ueeab\u8001\ueebb\u8002\u0000\u8002\ua6df\u8002\ua700"+
"\u8002\ub739\u8002\ub740\u8002\ub81d\u8002\ub820\u8002\ucea1\u8002\uceb0"+
"\u8002\uebe0\u8002\uf800\u8002\ufa1d\u8003\u0000\u8003\u134a\u8003\u1350"+
"\u8003\u23af\u0002\u0000\n\n``\u01f4\u0000\u0002\u0001\u0000\u0000\u0000"+
"\u0000\u0006\u0001\u0000\u0000\u0000\u0000\b\u0001\u0000\u0000\u0000\u0000"+
"\n\u0001\u0000\u0000\u0000\u0000\f\u0001\u0000\u0000\u0000\u0000\u000e"+
"\u0001\u0000\u0000\u0000\u0000\u0010\u0001\u0000\u0000\u0000\u0000\u0012"+
"\u0001\u0000\u0000\u0000\u0000\u0014\u0001\u0000\u0000\u0000\u0000\u0016"+
"\u0001\u0000\u0000\u0000\u0000\u0018\u0001\u0000\u0000\u0000\u0000\u001a"+
"\u0001\u0000\u0000\u0000\u0000\u001c\u0001\u0000\u0000\u0000\u0000\u001e"+
"\u0001\u0000\u0000\u0000\u0000 \u0001\u0000\u0000\u0000\u0000\"\u0001"+
"\u0000\u0000\u0000\u0000$\u0001\u0000\u0000\u0000\u0000&\u0001\u0000\u0000"+
"\u0000\u0000(\u0001\u0000\u0000\u0000\u0000*\u0001\u0000\u0000\u0000\u0000"+
",\u0001\u0000\u0000\u0000\u0000.\u0001\u0000\u0000\u0000\u00000\u0001"+
"\u0000\u0000\u0000\u00002\u0001\u0000\u0000\u0000\u00004\u0001\u0000\u0000"+
"\u0000\u00006\u0001\u0000\u0000\u0000\u00008\u0001\u0000\u0000\u0000\u0000"+
":\u0001\u0000\u0000\u0000\u0000<\u0001\u0000\u0000\u0000\u0000>\u0001"+
"\u0000\u0000\u0000\u0000@\u0001\u0000\u0000\u0000\u0000B\u0001\u0000\u0000"+
"\u0000\u0000D\u0001\u0000\u0000\u0000\u0000F\u0001\u0000\u0000\u0000\u0000"+
"H\u0001\u0000\u0000\u0000\u0000J\u0001\u0000\u0000\u0000\u0000L\u0001"+
"\u0000\u0000\u0000\u0000N\u0001\u0000\u0000\u0000\u0000P\u0001\u0000\u0000"+
"\u0000\u0000R\u0001\u0000\u0000\u0000\u0000T\u0001\u0000\u0000\u0000\u0000"+
"V\u0001\u0000\u0000\u0000\u0000X\u0001\u0000\u0000\u0000\u0000Z\u0001"+
"\u0000\u0000\u0000\u0000\\\u0001\u0000\u0000\u0000\u0000^\u0001\u0000"+
"\u0000\u0000\u0000`\u0001\u0000\u0000\u0000\u0000b\u0001\u0000\u0000\u0000"+
"\u0000d\u0001\u0000\u0000\u0000\u0000f\u0001\u0000\u0000\u0000\u0000h"+
"\u0001\u0000\u0000\u0000\u0000j\u0001\u0000\u0000\u0000\u0000l\u0001\u0000"+
"\u0000\u0000\u0000n\u0001\u0000\u0000\u0000\u0000p\u0001\u0000\u0000\u0000"+
"\u0000r\u0001\u0000\u0000\u0000\u0000t\u0001\u0000\u0000\u0000\u0000v"+
"\u0001\u0000\u0000\u0000\u0000x\u0001\u0000\u0000\u0000\u0000z\u0001\u0000"+
"\u0000\u0000\u0000|\u0001\u0000\u0000\u0000\u0001\u008e\u0001\u0000\u0000"+
"\u0000\u0001\u0090\u0001\u0000\u0000\u0000\u0001\u0092\u0001\u0000\u0000"+
"\u0000\u0001\u0094\u0001\u0000\u0000\u0000\u0002\u0096\u0001\u0000\u0000"+
"\u0000\u0004\u009b\u0001\u0000\u0000\u0000\u0006\u009e\u0001\u0000\u0000"+
"\u0000\b\u00a4\u0001\u0000\u0000\u0000\n\u00a7\u0001\u0000\u0000\u0000"+
"\f\u00a9\u0001\u0000\u0000\u0000\u000e\u00ac\u0001\u0000\u0000\u0000\u0010"+
"\u00ae\u0001\u0000\u0000\u0000\u0012\u00b0\u0001\u0000\u0000\u0000\u0014"+
"\u00b2\u0001\u0000\u0000\u0000\u0016\u00b4\u0001\u0000\u0000\u0000\u0018"+
"\u00b6\u0001\u0000\u0000\u0000\u001a\u00b8\u0001\u0000\u0000\u0000\u001c"+
"\u00ba\u0001\u0000\u0000\u0000\u001e\u00bc\u0001\u0000\u0000\u0000 \u00be"+
"\u0001\u0000\u0000\u0000\"\u00c0\u0001\u0000\u0000\u0000$\u00c2\u0001"+
"\u0000\u0000\u0000&\u00c4\u0001\u0000\u0000\u0000(\u00c6\u0001\u0000\u0000"+
"\u0000*\u00c9\u0001\u0000\u0000\u0000,\u00cb\u0001\u0000\u0000\u0000."+
"\u00ce\u0001\u0000\u0000\u00000\u00d1\u0001\u0000\u0000\u00002\u00d3\u0001"+
"\u0000\u0000\u00004\u00d6\u0001\u0000\u0000\u00006\u00d8\u0001\u0000\u0000"+
"\u00008\u00db\u0001\u0000\u0000\u0000:\u00dd\u0001\u0000\u0000\u0000<"+
"\u00e0\u0001\u0000\u0000\u0000>\u00e3\u0001\u0000\u0000\u0000@\u00e6\u0001"+
"\u0000\u0000\u0000B\u00e9\u0001\u0000\u0000\u0000D\u00eb\u0001\u0000\u0000"+
"\u0000F\u00ee\u0001\u0000\u0000\u0000H\u00f1\u0001\u0000\u0000\u0000J"+
"\u00f3\u0001\u0000\u0000\u0000L\u00f6\u0001\u0000\u0000\u0000N\u00f8\u0001"+
"\u0000\u0000\u0000P\u00fd\u0001\u0000\u0000\u0000R\u0102\u0001\u0000\u0000"+
"\u0000T\u0106\u0001\u0000\u0000\u0000V\u0109\u0001\u0000\u0000\u0000X"+
"\u010d\u0001\u0000\u0000\u0000Z\u0112\u0001\u0000\u0000\u0000\\\u0118"+
"\u0001\u0000\u0000\u0000^\u011c\u0001\u0000\u0000\u0000`\u0121\u0001\u0000"+
"\u0000\u0000b\u0123\u0001\u0000\u0000\u0000d\u012b\u0001\u0000\u0000\u0000"+
"f\u012e\u0001\u0000\u0000\u0000h\u0131\u0001\u0000\u0000\u0000j\u0134"+
"\u0001\u0000\u0000\u0000l\u0137\u0001\u0000\u0000\u0000n\u013a\u0001\u0000"+
"\u0000\u0000p\u013f\u0001\u0000\u0000\u0000r\u0176\u0001\u0000\u0000\u0000"+
"t\u0179\u0001\u0000\u0000\u0000v\u0182\u0001\u0000\u0000\u0000x\u0184"+
"\u0001\u0000\u0000\u0000z\u018f\u0001\u0000\u0000\u0000|\u019a\u0001\u0000"+
"\u0000\u0000~\u01a5\u0001\u0000\u0000\u0000\u0080\u01a7\u0001\u0000\u0000"+
"\u0000\u0082\u01a9\u0001\u0000\u0000\u0000\u0084\u01c3\u0001\u0000\u0000"+
"\u0000\u0086\u01c5\u0001\u0000\u0000\u0000\u0088\u01c7\u0001\u0000\u0000"+
"\u0000\u008a\u01ca\u0001\u0000\u0000\u0000\u008c\u01cc\u0001\u0000\u0000"+
"\u0000\u008e\u01ce\u0001\u0000\u0000\u0000\u0090\u01d1\u0001\u0000\u0000"+
"\u0000\u0092\u01d8\u0001\u0000\u0000\u0000\u0094\u01da\u0001\u0000\u0000"+
"\u0000\u0096\u0097\u0005;\u0000\u0000\u0097\u0003\u0001\u0000\u0000\u0000"+
"\u0098\u0099\u0005\r\u0000\u0000\u0099\u009c\u0005\n\u0000\u0000\u009a"+
"\u009c\u0007\u0000\u0000\u0000\u009b\u0098\u0001\u0000\u0000\u0000\u009b"+
"\u009a\u0001\u0000\u0000\u0000\u009c\u0005\u0001\u0000\u0000\u0000\u009d"+
"\u009f\u0007\u0001\u0000\u0000\u009e\u009d\u0001\u0000\u0000\u0000\u009f"+
"\u00a0\u0001\u0000\u0000\u0000\u00a0\u009e\u0001\u0000\u0000\u0000\u00a0"+
"\u00a1\u0001\u0000\u0000\u0000\u00a1\u00a2\u0001\u0000\u0000\u0000\u00a2"+
"\u00a3\u0006\u0002\u0000\u0000\u00a3\u0007\u0001\u0000\u0000\u0000\u00a4"+
"\u00a5\u0005+\u0000\u0000\u00a5\u00a6\u0005+\u0000\u0000\u00a6\t\u0001"+
"\u0000\u0000\u0000\u00a7\u00a8\u0005+\u0000\u0000\u00a8\u000b\u0001\u0000"+
"\u0000\u0000\u00a9\u00aa\u0005-\u0000\u0000\u00aa\u00ab\u0005-\u0000\u0000"+
"\u00ab\r\u0001\u0000\u0000\u0000\u00ac\u00ad\u0005-\u0000\u0000\u00ad"+
"\u000f\u0001\u0000\u0000\u0000\u00ae\u00af\u0005:\u0000\u0000\u00af\u0011"+
"\u0001\u0000\u0000\u0000\u00b0\u00b1\u0005.\u0000\u0000\u00b1\u0013\u0001"+
"\u0000\u0000\u0000\u00b2\u00b3\u0005,\u0000\u0000\u00b3\u0015\u0001\u0000"+
"\u0000\u0000\u00b4\u00b5\u0005*\u0000\u0000\u00b5\u0017\u0001\u0000\u0000"+
"\u0000\u00b6\u00b7\u0005/\u0000\u0000\u00b7\u0019\u0001\u0000\u0000\u0000"+
"\u00b8\u00b9\u0005%\u0000\u0000\u00b9\u001b\u0001\u0000\u0000\u0000\u00ba"+
"\u00bb\u0005(\u0000\u0000\u00bb\u001d\u0001\u0000\u0000\u0000\u00bc\u00bd"+
"\u0005)\u0000\u0000\u00bd\u001f\u0001\u0000\u0000\u0000\u00be\u00bf\u0005"+
"[\u0000\u0000\u00bf!\u0001\u0000\u0000\u0000\u00c0\u00c1\u0005]\u0000"+
"\u0000\u00c1#\u0001\u0000\u0000\u0000\u00c2\u00c3\u0005#\u0000\u0000\u00c3"+
"%\u0001\u0000\u0000\u0000\u00c4\u00c5\u0005@\u0000\u0000\u00c5\'\u0001"+
"\u0000\u0000\u0000\u00c6\u00c7\u0005^\u0000\u0000\u00c7\u00c8\u0005[\u0000"+
"\u0000\u00c8)\u0001\u0000\u0000\u0000\u00c9\u00ca\u0005^\u0000\u0000\u00ca"+
"+\u0001\u0000\u0000\u0000\u00cb\u00cc\u0005!\u0000\u0000\u00cc\u00cd\u0005"+
"=\u0000\u0000\u00cd-\u0001\u0000\u0000\u0000\u00ce\u00cf\u0005!\u0000"+
"\u0000\u00cf\u00d0\u0005[\u0000\u0000\u00d0/\u0001\u0000\u0000\u0000\u00d1"+
"\u00d2\u0005!\u0000\u0000\u00d21\u0001\u0000\u0000\u0000\u00d3\u00d4\u0005"+
"=\u0000\u0000\u00d4\u00d5\u0005=\u0000\u0000\u00d53\u0001\u0000\u0000"+
"\u0000\u00d6\u00d7\u0005=\u0000\u0000\u00d75\u0001\u0000\u0000\u0000\u00d8"+
"\u00d9\u0005&\u0000\u0000\u00d9\u00da\u0005&\u0000\u0000\u00da7\u0001"+
"\u0000\u0000\u0000\u00db\u00dc\u0005&\u0000\u0000\u00dc9\u0001\u0000\u0000"+
"\u0000\u00dd\u00de\u0005|\u0000\u0000\u00de\u00df\u0005|\u0000\u0000\u00df"+
";\u0001\u0000\u0000\u0000\u00e0\u00e1\u0005?\u0000\u0000\u00e1\u00e2\u0005"+
"[\u0000\u0000\u00e2=\u0001\u0000\u0000\u0000\u00e3\u00e4\u0005?\u0000"+
"\u0000\u00e4\u00e5\u0005:\u0000\u0000\u00e5?\u0001\u0000\u0000\u0000\u00e6"+
"\u00e7\u0005?\u0000\u0000\u00e7\u00e8\u0005.\u0000\u0000\u00e8A\u0001"+
"\u0000\u0000\u0000\u00e9\u00ea\u0005?\u0000\u0000\u00eaC\u0001\u0000\u0000"+
"\u0000\u00eb\u00ec\u0005$\u0000\u0000\u00ec\u00ed\u0005[\u0000\u0000\u00ed"+
"E\u0001\u0000\u0000\u0000\u00ee\u00ef\u0005>\u0000\u0000\u00ef\u00f0\u0005"+
"=\u0000\u0000\u00f0G\u0001\u0000\u0000\u0000\u00f1\u00f2\u0005>\u0000"+
"\u0000\u00f2I\u0001\u0000\u0000\u0000\u00f3\u00f4\u0005<\u0000\u0000\u00f4"+
"\u00f5\u0005=\u0000\u0000\u00f5K\u0001\u0000\u0000\u0000\u00f6\u00f7\u0005"+
"<\u0000\u0000\u00f7M\u0001\u0000\u0000\u0000\u00f8\u00f9\u0005{\u0000"+
"\u0000\u00f9\u00fa\u0006&\u0001\u0000\u00fa\u00fb\u0001\u0000\u0000\u0000"+
"\u00fb\u00fc\u0006&\u0002\u0000\u00fcO\u0001\u0000\u0000\u0000\u00fd\u00fe"+
"\u0005}\u0000\u0000\u00fe\u00ff\u0006\'\u0003\u0000\u00ff\u0100\u0001"+
"\u0000\u0000\u0000\u0100\u0101\u0006\'\u0004\u0000\u0101Q\u0001\u0000"+
"\u0000\u0000\u0102\u0103\u0005`\u0000\u0000\u0103\u0104\u0001\u0000\u0000"+
"\u0000\u0104\u0105\u0006(\u0005\u0000\u0105S\u0001\u0000\u0000\u0000\u0106"+
"\u0107\u0005o\u0000\u0000\u0107\u0108\u0005r\u0000\u0000\u0108U\u0001"+
"\u0000\u0000\u0000\u0109\u010a\u0005a\u0000\u0000\u010a\u010b\u0005n\u0000"+
"\u0000\u010b\u010c\u0005d\u0000\u0000\u010cW\u0001\u0000\u0000\u0000\u010d"+
"\u010e\u0005t\u0000\u0000\u010e\u010f\u0005r\u0000\u0000\u010f\u0110\u0005"+
"u\u0000\u0000\u0110\u0111\u0005e\u0000\u0000\u0111Y\u0001\u0000\u0000"+
"\u0000\u0112\u0113\u0005f\u0000\u0000\u0113\u0114\u0005a\u0000\u0000\u0114"+
"\u0115\u0005l\u0000\u0000\u0115\u0116\u0005s\u0000\u0000\u0116\u0117\u0005"+
"e\u0000\u0000\u0117[\u0001\u0000\u0000\u0000\u0118\u0119\u0005n\u0000"+
"\u0000\u0119\u011a\u0005e\u0000\u0000\u011a\u011b\u0005w\u0000\u0000\u011b"+
"]\u0001\u0000\u0000\u0000\u011c\u011d\u0005n\u0000\u0000\u011d\u011e\u0005"+
"u\u0000\u0000\u011e\u011f\u0005l\u0000\u0000\u011f\u0120\u0005l\u0000"+
"\u0000\u0120_\u0001\u0000\u0000\u0000\u0121\u0122\u0005T\u0000\u0000\u0122"+
"a\u0001\u0000\u0000\u0000\u0123\u0124\u0005m\u0000\u0000\u0124\u0125\u0005"+
"a\u0000\u0000\u0125\u0126\u0005t\u0000\u0000\u0126\u0127\u0005c\u0000"+
"\u0000\u0127\u0128\u0005h\u0000\u0000\u0128\u0129\u0005e\u0000\u0000\u0129"+
"\u012a\u0005s\u0000\u0000\u012ac\u0001\u0000\u0000\u0000\u012b\u012c\u0005"+
"g\u0000\u0000\u012c\u012d\u0005t\u0000\u0000\u012de\u0001\u0000\u0000"+
"\u0000\u012e\u012f\u0005g\u0000\u0000\u012f\u0130\u0005e\u0000\u0000\u0130"+
"g\u0001\u0000\u0000\u0000\u0131\u0132\u0005l\u0000\u0000\u0132\u0133\u0005"+
"e\u0000\u0000\u0133i\u0001\u0000\u0000\u0000\u0134\u0135\u0005l\u0000"+
"\u0000\u0135\u0136\u0005t\u0000\u0000\u0136k\u0001\u0000\u0000\u0000\u0137"+
"\u0138\u0005e\u0000\u0000\u0138\u0139\u0005q\u0000\u0000\u0139m\u0001"+
"\u0000\u0000\u0000\u013a\u013b\u0005n\u0000\u0000\u013b\u013c\u0005e\u0000"+
"\u0000\u013co\u0001\u0000\u0000\u0000\u013d\u0140\u0003\u008aD\u0000\u013e"+
"\u0140\u0005_\u0000\u0000\u013f\u013d\u0001\u0000\u0000\u0000\u013f\u013e"+
"\u0001\u0000\u0000\u0000\u0140\u0146\u0001\u0000\u0000\u0000\u0141\u0145"+
"\u0003\u008aD\u0000\u0142\u0145\u0003\u008cE\u0000\u0143\u0145\u0007\u0002"+
"\u0000\u0000\u0144\u0141\u0001\u0000\u0000\u0000\u0144\u0142\u0001\u0000"+
"\u0000\u0000\u0144\u0143\u0001\u0000\u0000\u0000\u0145\u0148\u0001\u0000"+
"\u0000\u0000\u0146\u0144\u0001\u0000\u0000\u0000\u0146\u0147\u0001\u0000"+
"\u0000\u0000\u0147q\u0001\u0000\u0000\u0000\u0148\u0146\u0001\u0000\u0000"+
"\u0000\u0149\u014b\u0005.\u0000\u0000\u014a\u014c\u0003\u0082@\u0000\u014b"+
"\u014a\u0001\u0000\u0000\u0000\u014c\u014d\u0001\u0000\u0000\u0000\u014d"+
"\u014b\u0001\u0000\u0000\u0000\u014d\u014e\u0001\u0000\u0000\u0000\u014e"+
"\u0150\u0001\u0000\u0000\u0000\u014f\u0151\u0003\u0084A\u0000\u0150\u014f"+
"\u0001\u0000\u0000\u0000\u0150\u0151\u0001\u0000\u0000\u0000\u0151\u0153"+
"\u0001\u0000\u0000\u0000\u0152\u0154\u0003\u0088C\u0000\u0153\u0152\u0001"+
"\u0000\u0000\u0000\u0153\u0154\u0001\u0000\u0000\u0000\u0154\u0177\u0001"+
"\u0000\u0000\u0000\u0155\u0157\u0003\u0082@\u0000\u0156\u0155\u0001\u0000"+
"\u0000\u0000\u0157\u0158\u0001\u0000\u0000\u0000\u0158\u0156\u0001\u0000"+
"\u0000\u0000\u0158\u0159\u0001\u0000\u0000\u0000\u0159\u015a\u0001\u0000"+
"\u0000\u0000\u015a\u015c\u0005.\u0000\u0000\u015b\u015d\u0003\u0082@\u0000"+
"\u015c\u015b\u0001\u0000\u0000\u0000\u015d\u015e\u0001\u0000\u0000\u0000"+
"\u015e\u015c\u0001\u0000\u0000\u0000\u015e\u015f\u0001\u0000\u0000\u0000"+
"\u015f\u0161\u0001\u0000\u0000\u0000\u0160\u0162\u0003\u0084A\u0000\u0161"+
"\u0160\u0001\u0000\u0000\u0000\u0161\u0162\u0001\u0000\u0000\u0000\u0162"+
"\u0164\u0001\u0000\u0000\u0000\u0163\u0165\u0003\u0088C\u0000\u0164\u0163"+
"\u0001\u0000\u0000\u0000\u0164\u0165\u0001\u0000\u0000\u0000\u0165\u0177"+
"\u0001\u0000\u0000\u0000\u0166\u0168\u0003\u0082@\u0000\u0167\u0166\u0001"+
"\u0000\u0000\u0000\u0168\u0169\u0001\u0000\u0000\u0000\u0169\u0167\u0001"+
"\u0000\u0000\u0000\u0169\u016a\u0001\u0000\u0000\u0000\u016a\u016b\u0001"+
"\u0000\u0000\u0000\u016b\u016d\u0003\u0084A\u0000\u016c\u016e\u0003\u0088"+
"C\u0000\u016d\u016c\u0001\u0000\u0000\u0000\u016d\u016e\u0001\u0000\u0000"+
"\u0000\u016e\u0177\u0001\u0000\u0000\u0000\u016f\u0171\u0003\u0082@\u0000"+
"\u0170\u016f\u0001\u0000\u0000\u0000\u0171\u0172\u0001\u0000\u0000\u0000"+
"\u0172\u0170\u0001\u0000\u0000\u0000\u0172\u0173\u0001\u0000\u0000\u0000"+
"\u0173\u0174\u0001\u0000\u0000\u0000\u0174\u0175\u0003\u0088C\u0000\u0175"+
"\u0177\u0001\u0000\u0000\u0000\u0176\u0149\u0001\u0000\u0000\u0000\u0176"+
"\u0156\u0001\u0000\u0000\u0000\u0176\u0167\u0001\u0000\u0000\u0000\u0176"+
"\u0170\u0001\u0000\u0000\u0000\u0177s\u0001\u0000\u0000\u0000\u0178\u017a"+
"\u0003\u0082@\u0000\u0179\u0178\u0001\u0000\u0000\u0000\u017a\u017b\u0001"+
"\u0000\u0000\u0000\u017b\u0179\u0001\u0000\u0000\u0000\u017b\u017c\u0001"+
"\u0000\u0000\u0000\u017c\u017e\u0001\u0000\u0000\u0000\u017d\u017f\u0003"+
"~>\u0000\u017e\u017d\u0001\u0000\u0000\u0000\u017e\u017f\u0001\u0000\u0000"+
"\u0000\u017fu\u0001\u0000\u0000\u0000\u0180\u0183\u0003x;\u0000\u0181"+
"\u0183\u0003z<\u0000\u0182\u0180\u0001\u0000\u0000\u0000\u0182\u0181\u0001"+
"\u0000\u0000\u0000\u0183w\u0001\u0000\u0000\u0000\u0184\u018a\u0005\'"+
"\u0000\u0000\u0185\u0186\u0005\'\u0000\u0000\u0186\u0189\u0005\'\u0000"+
"\u0000\u0187\u0189\b\u0003\u0000\u0000\u0188\u0185\u0001\u0000\u0000\u0000"+
"\u0188\u0187\u0001\u0000\u0000\u0000\u0189\u018c\u0001\u0000\u0000\u0000"+
"\u018a\u0188\u0001\u0000\u0000\u0000\u018a\u018b\u0001\u0000\u0000\u0000"+
"\u018b\u018d\u0001\u0000\u0000\u0000\u018c\u018a\u0001\u0000\u0000\u0000"+
"\u018d\u018e\u0005\'\u0000\u0000\u018ey\u0001\u0000\u0000\u0000\u018f"+
"\u0195\u0005\"\u0000\u0000\u0190\u0191\u0005\"\u0000\u0000\u0191\u0194"+
"\u0005\"\u0000\u0000\u0192\u0194\b\u0004\u0000\u0000\u0193\u0190\u0001"+
"\u0000\u0000\u0000\u0193\u0192\u0001\u0000\u0000\u0000\u0194\u0197\u0001"+
"\u0000\u0000\u0000\u0195\u0193\u0001\u0000\u0000\u0000\u0195\u0196\u0001"+
"\u0000\u0000\u0000\u0196\u0198\u0001\u0000\u0000\u0000\u0197\u0195\u0001"+
"\u0000\u0000\u0000\u0198\u0199\u0005\"\u0000\u0000\u0199{\u0001\u0000"+
"\u0000\u0000\u019a\u019b\u0005$\u0000\u0000\u019b\u019c\u0005{\u0000\u0000"+
"\u019c\u01a0\u0001\u0000\u0000\u0000\u019d\u019f\t\u0000\u0000\u0000\u019e"+
"\u019d\u0001\u0000\u0000\u0000\u019f\u01a2\u0001\u0000\u0000\u0000\u01a0"+
"\u01a1\u0001\u0000\u0000\u0000\u01a0\u019e\u0001\u0000\u0000\u0000\u01a1"+
"\u01a3\u0001\u0000\u0000\u0000\u01a2\u01a0\u0001\u0000\u0000\u0000\u01a3"+
"\u01a4\u0005}\u0000\u0000\u01a4}\u0001\u0000\u0000\u0000\u01a5\u01a6\u0007"+
"\u0005\u0000\u0000\u01a6\u007f\u0001\u0000\u0000\u0000\u01a7\u01a8\u0007"+
"\u0006\u0000\u0000\u01a8\u0081\u0001\u0000\u0000\u0000\u01a9\u01aa\u0007"+
"\u0007\u0000\u0000\u01aa\u0083\u0001\u0000\u0000\u0000\u01ab\u01af\u0005"+
"e\u0000\u0000\u01ac\u01ae\u0003\u0086B\u0000\u01ad\u01ac\u0001\u0000\u0000"+
"\u0000\u01ae\u01b1\u0001\u0000\u0000\u0000\u01af\u01ad\u0001\u0000\u0000"+
"\u0000\u01af\u01b0\u0001\u0000\u0000\u0000\u01b0\u01b3\u0001\u0000\u0000"+
"\u0000\u01b1\u01af\u0001\u0000\u0000\u0000\u01b2\u01b4\u0003\u0082@\u0000"+
"\u01b3\u01b2\u0001\u0000\u0000\u0000\u01b4\u01b5\u0001\u0000\u0000\u0000"+
"\u01b5\u01b3\u0001\u0000\u0000\u0000\u01b5\u01b6\u0001\u0000\u0000\u0000"+
"\u01b6\u01c4\u0001\u0000\u0000\u0000\u01b7\u01bb\u0005E\u0000\u0000\u01b8"+
"\u01ba\u0003\u0086B\u0000\u01b9\u01b8\u0001\u0000\u0000\u0000\u01ba\u01bd"+
"\u0001\u0000\u0000\u0000\u01bb\u01b9\u0001\u0000\u0000\u0000\u01bb\u01bc"+
"\u0001\u0000\u0000\u0000\u01bc\u01bf\u0001\u0000\u0000\u0000\u01bd\u01bb"+
"\u0001\u0000\u0000\u0000\u01be\u01c0\u0003\u0082@\u0000\u01bf\u01be\u0001"+
"\u0000\u0000\u0000\u01c0\u01c1\u0001\u0000\u0000\u0000\u01c1\u01bf\u0001"+
"\u0000\u0000\u0000\u01c1\u01c2\u0001\u0000\u0000\u0000\u01c2\u01c4\u0001"+
"\u0000\u0000\u0000\u01c3\u01ab\u0001\u0000\u0000\u0000\u01c3\u01b7\u0001"+
"\u0000\u0000\u0000\u01c4\u0085\u0001\u0000\u0000\u0000\u01c5\u01c6\u0007"+
"\b\u0000\u0000\u01c6\u0087\u0001\u0000\u0000\u0000\u01c7\u01c8\u0007\t"+
"\u0000\u0000\u01c8\u0089\u0001\u0000\u0000\u0000\u01c9\u01cb\u0007\n\u0000"+
"\u0000\u01ca\u01c9\u0001\u0000\u0000\u0000\u01cb\u008b\u0001\u0000\u0000"+
"\u0000\u01cc\u01cd\u0007\u0007\u0000\u0000\u01cd\u008d\u0001\u0000\u0000"+
"\u0000\u01ce\u01cf\u0005`\u0000\u0000\u01cf\u01d0\u0005`\u0000\u0000\u01d0"+
"\u008f\u0001\u0000\u0000\u0000\u01d1\u01d2\u0005#\u0000\u0000\u01d2\u01d3"+
"\u0005{\u0000\u0000\u01d3\u01d4\u0001\u0000\u0000\u0000\u01d4\u01d5\u0006"+
"G\u0006\u0000\u01d5\u01d6\u0001\u0000\u0000\u0000\u01d6\u01d7\u0006G\u0002"+
"\u0000\u01d7\u0091\u0001\u0000\u0000\u0000\u01d8\u01d9\b\u000b\u0000\u0000"+
"\u01d9\u0093\u0001\u0000\u0000\u0000\u01da\u01db\u0005`\u0000\u0000\u01db"+
"\u01dc\u0001\u0000\u0000\u0000\u01dc\u01dd\u0006I\u0007\u0000\u01dd\u01de"+
"\u0006I\u0004\u0000\u01de\u0095\u0001\u0000\u0000\u0000 \u0000\u0001\u009b"+
"\u00a0\u013f\u0144\u0146\u014d\u0150\u0153\u0158\u015e\u0161\u0164\u0169"+
"\u016d\u0172\u0176\u017b\u017e\u0182\u0188\u018a\u0193\u0195\u01a0\u01af"+
"\u01b5\u01bb\u01c1\u01c3\u01ca\b\u0000\u0001\u0000\u0001&\u0000\u0005"+
"\u0000\u0000\u0001\'\u0001\u0004\u0000\u0000\u0005\u0001\u0000\u0001G"+
"\u0002\u0007(\u0000";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {

View File

@@ -348,6 +348,18 @@ public class SpelParserBaseListener implements SpelParserListener {
* <p>The default implementation does nothing.</p>
*/
@Override public void exitInputParameter(SpelParser.InputParameterContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterPropertyPlaceHolder(SpelParser.PropertyPlaceHolderContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitPropertyPlaceHolder(SpelParser.PropertyPlaceHolderContext ctx) { }
/**
* {@inheritDoc}

View File

@@ -289,4 +289,14 @@ public interface SpelParserListener extends ParseTreeListener {
* @param ctx the parse tree
*/
void exitInputParameter(SpelParser.InputParameterContext ctx);
/**
* Enter a parse tree produced by {@link SpelParser#propertyPlaceHolder}.
* @param ctx the parse tree
*/
void enterPropertyPlaceHolder(SpelParser.PropertyPlaceHolderContext ctx);
/**
* Exit a parse tree produced by {@link SpelParser#propertyPlaceHolder}.
* @param ctx the parse tree
*/
void exitPropertyPlaceHolder(SpelParser.PropertyPlaceHolderContext ctx);
}

View File

@@ -19,7 +19,8 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemTy
public enum SpelProblemType implements ProblemType {
JAVA_SPEL_EXPRESSION_SYNTAX(ERROR, "SpEL parser raised a ParseException", "SpEL Expression Syntax");
JAVA_SPEL_EXPRESSION_SYNTAX(ERROR, "SpEL parser raised a ParseException", "SpEL Expression Syntax"),
PROPERTY_PLACE_HOLDER_SYNTAX(ERROR, "Property place holder raised a ParseException", "Property Place Holder Syntax");
private final ProblemSeverity defaultSeverity;
private String description;

View File

@@ -0,0 +1,35 @@
/*******************************************************************************
* 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.data.jpa.queries;
import java.util.stream.Stream;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.TerminalNode;
public class AntlrUtils {
public static Stream<Token> getAllLeafs(ParserRuleContext ctx) {
if (ctx.children == null) {
return Stream.empty();
}
return ctx.children.stream().flatMap(n -> {
if (n instanceof ParserRuleContext prc) {
return getAllLeafs(prc);
} else if (n instanceof TerminalNode tn) {
return Stream.of(tn.getSymbol());
}
return Stream.empty();
});
}
}

View File

@@ -26,7 +26,6 @@ import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ConsoleErrorListener;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.Token;
@@ -201,7 +200,7 @@ public class MySqlSemanticTokens implements SemanticTokensDataProvider {
@Override
public void exitUdfFunctionCall(UdfFunctionCallContext fc) {
if (fc.fullId() != null) {
List<Token> ls = getAllLeafs(fc.fullId()).toList();
List<Token> ls = AntlrUtils.getAllLeafs(fc.fullId()).toList();
if (!ls.isEmpty()) {
semantics.put(ls.get(ls.size() - 1), "method");
}
@@ -211,13 +210,13 @@ public class MySqlSemanticTokens implements SemanticTokensDataProvider {
@Override
public void exitParameter(ParameterContext ctx) {
if (ctx.dottedId() != null) {
getAllLeafs(ctx.dottedId()).forEach(t -> semantics.put(t, "parameter"));
AntlrUtils.getAllLeafs(ctx.dottedId()).forEach(t -> semantics.put(t, "parameter"));
}
if (ctx.uid() != null) {
getAllLeafs(ctx.uid()).forEach(t -> semantics.put(t, "parameter"));
AntlrUtils.getAllLeafs(ctx.uid()).forEach(t -> semantics.put(t, "parameter"));
}
if (ctx.decimalLiteral() != null) {
getAllLeafs(ctx.decimalLiteral()).forEach(t -> semantics.put(t, "parameter"));
AntlrUtils.getAllLeafs(ctx.decimalLiteral()).forEach(t -> semantics.put(t, "parameter"));
}
}
@@ -278,17 +277,6 @@ public class MySqlSemanticTokens implements SemanticTokensDataProvider {
}
static Stream<Token> getAllLeafs(ParserRuleContext ctx) {
return ctx.children.stream().flatMap(n -> {
if (n instanceof ParserRuleContext prc) {
return getAllLeafs(prc);
} else if (n instanceof TerminalNode tn) {
return Stream.of(tn.getSymbol());
}
return Stream.empty();
});
}
}

View File

@@ -146,7 +146,7 @@ public class PostgreSqlSemanticTokens implements SemanticTokensDataProvider {
@Override
public void exitData_type(Data_typeContext dataType) {
if (dataType.identifier() != null) {
MySqlSemanticTokens.getAllLeafs(dataType.identifier())
AntlrUtils.getAllLeafs(dataType.identifier())
.filter(t -> t.getType() == PostgreSqlLexer.IDENTIFIER)
.forEach(t -> semantics.put(t, "type"));
}
@@ -155,11 +155,11 @@ public class PostgreSqlSemanticTokens implements SemanticTokensDataProvider {
@Override
public void exitParameter(ParameterContext param) {
if (param.identifier() != null) {
MySqlSemanticTokens.getAllLeafs(param.identifier()).forEach(t -> semantics.put(t, "parameter"));
AntlrUtils.getAllLeafs(param.identifier()).forEach(t -> semantics.put(t, "parameter"));
} else if (param.INTEGER_LITERAL() != null) {
semantics.put(param.INTEGER_LITERAL().getSymbol(), "parameter");
} else if (param.reserved_keyword() != null) {
MySqlSemanticTokens.getAllLeafs(param.reserved_keyword()).forEach(t -> semantics.put(t, "parameter"));
AntlrUtils.getAllLeafs(param.reserved_keyword()).forEach(t -> semantics.put(t, "parameter"));
}
}

View File

@@ -0,0 +1,161 @@
/*******************************************************************************
* 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.spel;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.antlr.v4.runtime.ANTLRErrorListener;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ConsoleErrorListener;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.Token;
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.commons.languageserver.semantic.tokens.SemanticTokenData;
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensDataProvider;
import org.springframework.ide.vscode.parser.placeholder.PropertyPlaceHolderBaseListener;
import org.springframework.ide.vscode.parser.placeholder.PropertyPlaceHolderLexer;
import org.springframework.ide.vscode.parser.placeholder.PropertyPlaceHolderParser;
import org.springframework.ide.vscode.parser.placeholder.PropertyPlaceHolderParser.DefaultValueContext;
import org.springframework.ide.vscode.parser.placeholder.PropertyPlaceHolderParser.KeyContext;
import org.springframework.ide.vscode.parser.placeholder.PropertyPlaceHolderParser.ValueContext;
public class PropertyPlaceHolderSemanticTokens implements SemanticTokensDataProvider {
private final Optional<Consumer<RecognitionException>> parseErrorHandler;
public PropertyPlaceHolderSemanticTokens(Optional<Consumer<RecognitionException>> parseErrorHandler) {
this.parseErrorHandler = parseErrorHandler;
}
@Override
public List<String> getTokenTypes() {
return List.of("property", "string", "operator");
}
@Override
public List<SemanticTokenData> computeTokens(String text, int initialOffset) {
PropertyPlaceHolderLexer lexer = new PropertyPlaceHolderLexer(CharStreams.fromString(text));
CommonTokenStream antlrTokens = new CommonTokenStream(lexer);
PropertyPlaceHolderParser parser = new PropertyPlaceHolderParser(antlrTokens);
Map<Token, String> semantics = new HashMap<>();
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
List<SemanticTokenData> tokens = new ArrayList<>();
parser.addParseListener(new PropertyPlaceHolderBaseListener() {
@Override
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 end = start + ctx.getText().length();
tokens.add(new SemanticTokenData(start, end, "property", new String[0]));
}
@Override
public void exitDefaultValue(DefaultValueContext ctx) {
AntlrUtils.getAllLeafs(ctx).forEach(semantics::remove);
if (ctx.Colon() != null) {
semantics.put(ctx.Colon().getSymbol(), "operator");
}
if (ctx.value() != null) {
ValueContext valueCtx = ctx.value();
int start = valueCtx.getStart().getStartIndex() + initialOffset;
int end = start + valueCtx.getText().length();
tokens.add(new SemanticTokenData(start, end, "string", new String[0]));
}
}
@Override
public void visitTerminal(TerminalNode node) {
processTerminalNode(node);
}
@Override
public void visitErrorNode(ErrorNode node) {
processTerminalNode(node);
}
private void processTerminalNode(TerminalNode node) {
Token token = node.getSymbol();
switch (token.getType()) {
case PropertyPlaceHolderLexer.Space:
case PropertyPlaceHolderLexer.LineBreak:
case PropertyPlaceHolderLexer.EOF:
break;
case PropertyPlaceHolderLexer.Colon:
semantics.put(node.getSymbol(), "operator");
break;
default:
semantics.put(node.getSymbol(), "property");
}
}
});
parser.addErrorListener(new ANTLRErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
String msg, RecognitionException e) {
parseErrorHandler.ifPresent(h -> h.accept(e));
}
@Override
public void reportContextSensitivity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, int prediction,
ATNConfigSet configs) {
}
@Override
public void reportAttemptingFullContext(Parser recognizer, DFA dfa, int startIndex, int stopIndex,
BitSet conflictingAlts, ATNConfigSet configs) {
}
@Override
public void reportAmbiguity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact,
BitSet ambigAlts, ATNConfigSet configs) {
}
});
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(),
new String[0]))
.collect(Collectors.toList()));
Collections.sort(tokens);
return tokens;
}
}

View File

@@ -10,20 +10,29 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.spel;
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.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.parser.placeholder.PropertyPlaceHolderLexer;
import org.springframework.ide.vscode.parser.placeholder.PropertyPlaceHolderParser;
import org.springframework.ide.vscode.parser.spel.SpelLexer;
import org.springframework.ide.vscode.parser.spel.SpelParser;
public class SpelReconciler extends AntlrReconciler {
private boolean enabled;
private AntlrReconciler propertyHolderReconciler;
public SpelReconciler() {
super("SPEL", SpelParser.class, SpelLexer.class, "spelExpr", SpelProblemType.JAVA_SPEL_EXPRESSION_SYNTAX);
this.errorOnUnrecognizedTokens = false;
this.enabled = true;
this.propertyHolderReconciler = new AntlrReconciler("Place-Holder", PropertyPlaceHolderParser.class, PropertyPlaceHolderLexer.class, "start", SpelProblemType.PROPERTY_PLACE_HOLDER_SYNTAX);
}
public void setEnabled(boolean spelExpressionValidationEnabled) {
@@ -38,4 +47,42 @@ public class SpelReconciler extends AntlrReconciler {
super.reconcile(text, startPosition, problemCollector);
}
@Override
protected Parser createParser(String text, int startPosition, IProblemCollector problemCollector) throws Exception {
Parser parser = super.createParser(text, startPosition, 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);
}
}
@Override
public void visitTerminal(TerminalNode node) {
processTerminal(node);
}
@Override
public void visitErrorNode(ErrorNode node) {
processTerminal(node);
}
@Override
public void enterEveryRule(ParserRuleContext ctx) {
}
@Override
public void exitEveryRule(ParserRuleContext ctx) {
}
});
return parser;
}
}

View File

@@ -14,8 +14,10 @@ import static org.springframework.ide.vscode.parser.spel.SpelLexer.*;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -50,9 +52,11 @@ import org.springframework.ide.vscode.parser.spel.SpelParserBaseListener;
public class SpelSemanticTokens implements SemanticTokensDataProvider {
private final Optional<Consumer<RecognitionException>> parseErrorHandler;
private final PropertyPlaceHolderSemanticTokens propertyPlaceHolderSemanticTokens;
public SpelSemanticTokens(Optional<Consumer<RecognitionException>> parseErrorHandler) {
this.parseErrorHandler = parseErrorHandler;
this.propertyPlaceHolderSemanticTokens = new PropertyPlaceHolderSemanticTokens(parseErrorHandler);
}
public SpelSemanticTokens() {
@@ -61,7 +65,9 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider {
@Override
public List<String> getTokenTypes() {
return List.of("operator", "keyword", "type", "string", "number", "method", "property", "parameter");
LinkedHashSet<String> tokenTypes = new LinkedHashSet<>(List.of("operator", "keyword", "type", "string", "number", "method", "property", "parameter"));
tokenTypes.addAll(propertyPlaceHolderSemanticTokens.getTokenTypes());
return tokenTypes.stream().toList();
}
@Override
@@ -151,6 +157,9 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider {
case DOUBLE_QUOTED_STRING:
semantics.put(node.getSymbol(), "string");
break;
case PROPERTY_PLACE_HOLDER:
tokens.addAll(computeTokensFromPropertyPlaceHolderNode(node, initialOffset));
break;
}
}
@@ -260,5 +269,24 @@ public class SpelSemanticTokens implements SemanticTokensDataProvider {
return tokens;
}
private Collection<? extends SemanticTokenData> computeTokensFromPropertyPlaceHolderNode(TerminalNode node,
int initialOffset) {
List<SemanticTokenData> placeHolderTokens = new ArrayList<>();
int startPosition = initialOffset + 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));
// '}' operator
placeHolderTokens.add(new SemanticTokenData(placeHolderEndPosition, endPosition, "operator", new String[0]));
return placeHolderTokens;
}
}

View File

@@ -334,6 +334,12 @@
"label": "SpEL Expression Syntax",
"description": "SpEL parser raised a ParseException",
"defaultSeverity": "ERROR"
},
{
"code": "PROPERTY_PLACE_HOLDER_SYNTAX",
"label": "Property Place Holder Syntax",
"description": "Property place holder raised a ParseException",
"defaultSeverity": "ERROR"
}
]
},

View File

@@ -0,0 +1,59 @@
package org.springframework.ide.vscode.boot.java.spel;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
public class PropertyPlaceHolderSemanticTokensTest {
private PropertyPlaceHolderSemanticTokens provider = new PropertyPlaceHolderSemanticTokens(Optional.of(Assertions::fail));
@Test
void propertyWithDefault() {
List<SemanticTokenData> tokens = provider.computeTokens("server.port:5673", 0);
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]));
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(12, 16, "string", new String[0]));
}
@Test
void propertyOnly() {
List<SemanticTokenData> tokens = provider.computeTokens("server.port", 0);
assertThat(tokens.size()).isEqualTo(1);
assertThat(tokens.get(0)).isEqualTo(new SemanticTokenData(0, 11, "property", new String[0]));
}
@Test
void propertyWithEmptyDefaulValue() {
List<SemanticTokenData> tokens = provider.computeTokens("server.port:", 0);
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]));
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(12, 12, "string", new String[0]));
}
@Test
void error_1() {
provider = new PropertyPlaceHolderSemanticTokens(Optional.empty());
List<SemanticTokenData> tokens = provider.computeTokens("server.:", 0);
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]));
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(7, 8, "operator", new String[0]));
}
@Test
void error_2() {
provider = new PropertyPlaceHolderSemanticTokens(Optional.empty());
List<SemanticTokenData> tokens = provider.computeTokens("server.", 0);
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]));
}
}

View File

@@ -143,5 +143,17 @@ public class SpelSemanticTokensTest {
assertThat(tokens.get(8)).isEqualTo(new SemanticTokenData(21, 22, "operator", new String[0])); // )
}
@Test
void withPropertyPlaceHolder() {
List<SemanticTokenData> tokens = provider.computeTokens("${server.port:8080} == 8080", 0);
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
assertThat(tokens.get(2)).isEqualTo(new SemanticTokenData(13, 14, "operator", new String[0])); // :
assertThat(tokens.get(3)).isEqualTo(new SemanticTokenData(14, 18, "string", new String[0])); // 8080
assertThat(tokens.get(4)).isEqualTo(new SemanticTokenData(18, 19, "operator", new String[0])); // }
assertThat(tokens.get(5)).isEqualTo(new SemanticTokenData(20, 22, "operator", new String[0])); // ==
assertThat(tokens.get(6)).isEqualTo(new SemanticTokenData(23, 27, "number", new String[0])); // 8080
}
}

View File

@@ -12,6 +12,7 @@ package org.springframework.ide.vscode.boot.java.value.test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.File;
import java.net.URI;
@@ -43,6 +44,7 @@ import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
import org.springframework.ide.vscode.boot.editor.harness.PropertyIndexHarness;
import org.springframework.ide.vscode.boot.index.cache.IndexCache;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheVoid;
import org.springframework.ide.vscode.boot.java.SpelProblemType;
import org.springframework.ide.vscode.boot.java.handlers.BootJavaReconcileEngine;
import org.springframework.ide.vscode.boot.java.links.SourceLinkFactory;
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
@@ -330,7 +332,7 @@ public class ValueSpelExpressionValidationTest {
}
@Test
void testIgnoreSpelExpressionsWithPropertyPlaceholder() throws Exception {
void testSpelExpressionsWithPropertyPlaceholder_noErrors() throws Exception {
TextDocument doc = prepareDocument("@Value(\"onField\")", "@Value(value=\"#{${property.hello:false}}\")");
assertNotNull(doc);
@@ -340,6 +342,23 @@ public class ValueSpelExpressionValidationTest {
assertEquals(0, problems.size());
}
@Test
void testSpelExpressionsWithPropertyPlaceholder_withErrors() throws Exception {
TextDocument doc = prepareDocument("@Value(\"onField\")", "@Value(value=\"#{${property.}}\")");
assertNotNull(doc);
reconcileEngine.reconcile(doc, problemCollector);
List<ReconcileProblem> problems = problemCollector.getCollectedProblems();
assertEquals(1, problems.size());
ReconcileProblem problem = problems.get(0);
assertEquals(199, problem.getOffset());
assertEquals(0, problem.getLength());
assertEquals(SpelProblemType.PROPERTY_PLACE_HOLDER_SYNTAX, problem.getType());
assertTrue(problem.getMessage().startsWith("Place-Holder:"));
}
private TextDocument prepareDocument(String selectedAnnotation, String annotationStatementBeforeTest) throws Exception {
String content = IOUtils.toString(new URI(docUri), StandardCharsets.UTF_8);

View File

@@ -1068,6 +1068,18 @@
"HINT",
"ERROR"
]
},
"spring-boot.ls.problem.spel.PROPERTY_PLACE_HOLDER_SYNTAX": {
"type": "string",
"default": "ERROR",
"description": "Property place holder raised a ParseException",
"enum": [
"IGNORE",
"INFO",
"WARNING",
"HINT",
"ERROR"
]
}
}
},
@@ -1312,4 +1324,4 @@
"extensionDependencies": [
"redhat.java"
]
}
}