Merge pull request #279 from TouchInstinct/feature/text_processing

"Replace" template generation, Placeholder generation, Mask generation
This commit is contained in:
airatmeister 2022-12-22 14:45:46 +03:00 committed by GitHub
commit 39d045db1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 9208 additions and 0 deletions

1
text-processing/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

37
text-processing/README.md Normal file
View File

@ -0,0 +1,37 @@
text-processing
=====
### Общее описание
Модуль содержит функционал:
- Генерация "Replace" шаблона из регулярного выражения и возможность подстановки его в строку,
- Генерация Placeholder из регулярного выражения,
- Генерация маски для `EditText` из регулярного выражения и возможность его подстановки.
Модуль содержит класс `TextFormatter`, который в качестве аргумента принимает `String` в виде регулярного выражения.
* Функция `getFormattedText` - принимает входящий параметр в виде строки для форматирования, возвращает отформатированную строку,
* Функция `getPlaceholder` - возвращает Placeholder соответствующий регулярному выражению,
* Функция `getRegexReplace` - возвращает "Replace" шаблон регулярного выражения,
* Функция `mask` - принимает входящим параметром `EditText` и применяет к нему маску сгенерированую по регулярному выражению.
### Пример применения `textFormatter`
```kotlin
class MainActivity : Activity() {
/**
* replace шаблон - $1/$2
* placeholder - 12/34
* **/
private val textFormatter = TextFormatter("(\\d{2})\\/?(\\d{2})")
private lateinit var editText: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
editText = findViewById(R.id.editText)
editText.hint = textFormatter.getPlaceholder() //В результате placeholder будет 12/34
textFormatter.mask(editText) //Применение маски соответствующей регулярному выражению из textFormatter
}
}
```

View File

@ -0,0 +1,8 @@
apply from: "../android-configs/lib-config.gradle"
dependencies {
implementation 'org.antlr:antlr4:4.9.2'
implementation 'org.antlr:antlr4-runtime:4.9.2'
implementation 'ru.tinkoff.decoro:decoro:1.5.1'
testImplementation 'junit:junit:4.13.2'
}

View File

@ -0,0 +1 @@
<manifest package="ru.touchin.roboswag.textprocessing" />

View File

@ -0,0 +1,754 @@
/*
* Copyright (c) 2014-2022 by Bart Kiers
*
* The MIT license.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Project : PCRE Parser, an ANTLR 4 grammar for PCRE
* Developed by : Bart Kiers, bart@big-o.nl
* Also see : https://github.com/bkiers/pcre-parser
*/
grammar PCRE;
// Most single line comments above the lexer- and parser rules
// are copied from the official PCRE man pages (last updated:
// 10 January 2012): http://www.pcre.org/pcre.txt
parse
: alternation EOF
;
// ALTERNATION
//
// expr|expr|expr...
alternation
: expr ('|' expr)*
;
expr
: element*
;
element
: atom quantifier?
;
// QUANTIFIERS
//
// ? 0 or 1, greedy
// ?+ 0 or 1, possessive
// ?? 0 or 1, lazy
// * 0 or more, greedy
// *+ 0 or more, possessive
// *? 0 or more, lazy
// + 1 or more, greedy
// ++ 1 or more, possessive
// +? 1 or more, lazy
// {n} exactly n
// {n,m} at least n, no more than m, greedy
// {n,m}+ at least n, no more than m, possessive
// {n,m}? at least n, no more than m, lazy
// {n,} n or more, greedy
// {n,}+ n or more, possessive
// {n,}? n or more, lazy
quantifier
: '?' quantifier_type
| '+' quantifier_type
| '*' quantifier_type
| '{' number '}' quantifier_type
| '{' number ',' '}' quantifier_type
| '{' number ',' number '}' quantifier_type
;
quantifier_type
: '+'
| '?'
| /* nothing */
;
// CHARACTER CLASSES
//
// [...] positive character class
// [^...] negative character class
// [x-y] range (can be used for hex characters)
// [[:xxx:]] positive POSIX named set
// [[:^xxx:]] negative POSIX named set
//
// alnum alphanumeric
// alpha alphabetic
// ascii 0-127
// blank space or tab
// cntrl control character
// digit decimal digit
// graph printing, excluding space
// lower lower case letter
// print printing, including space
// punct printing, excluding alphanumeric
// space white space
// upper upper case letter
// word same as \w
// xdigit hexadecimal digit
//
// In PCRE, POSIX character set names recognize only ASCII characters by
// default, but some of them use Unicode properties if PCRE_UCP is set.
// You can use \Q...\E inside a character class.
character_class
: '[' '^' CharacterClassEnd Hyphen cc_atom+ ']'
| '[' '^' CharacterClassEnd cc_atom* ']'
| '[' '^' cc_atom+ ']'
| '[' CharacterClassEnd Hyphen cc_atom+ ']'
| '[' CharacterClassEnd cc_atom* ']'
| '[' cc_atom+ ']'
;
// BACKREFERENCES
//
// \n reference by number (can be ambiguous)
// \gn reference by number
// \g{n} reference by number
// \g{-n} relative reference by number
// \k<name> reference by name (Perl)
// \k'name' reference by name (Perl)
// \g{name} reference by name (Perl)
// \k{name} reference by name (.NET)
// (?P=name) reference by name (Python)
backreference
: backreference_or_octal
| '\\g' number
| '\\g' '{' number '}'
| '\\g' '{' '-' number '}'
| '\\k' '<' name '>'
| '\\k' '\'' name '\''
| '\\g' '{' name '}'
| '\\k' '{' name '}'
| '(' '?' 'P' '=' name ')'
;
backreference_or_octal
: octal_char
| Backslash digit
;
// CAPTURING
//
// (...) capturing group
// (?<name>...) named capturing group (Perl)
// (?'name'...) named capturing group (Perl)
// (?P<name>...) named capturing group (Python)
// (?:...) non-capturing group
// (?|...) non-capturing group; reset group numbers for
// capturing groups in each alternative
//
// ATOMIC GROUPS
//
// (?>...) atomic, non-capturing group
capture
: '(' '?' '<' name '>' alternation ')'
| '(' '?''\'' name '\'' alternation ')'
| '(' '?' 'P' '<' name '>' alternation ')'
| '(' alternation ')'
;
non_capture
: '(' '?' ':' alternation ')'
| '(' '?' '|' alternation ')'
| '(' '?' '>' alternation ')'
| '(' '?' option_flags ':' alternation ')'
;
// COMMENT
//
// (?#....) comment (not nestable)
comment
: '(' '?' '#' non_close_parens ')'
;
// OPTION SETTING
//
// (?i) caseless
// (?J) allow duplicate names
// (?m) multiline
// (?s) single line (dotall)
// (?U) default ungreedy (lazy)
// (?x) extended (ignore white space)
// (?-...) unset option(s)
//
// The following are recognized only at the start of a pattern or after
// one of the newline-setting options with similar syntax:
//
// (*NO_START_OPT) no start-match optimization (PCRE_NO_START_OPTIMIZE)
// (*UTF8) set UTF-8 mode: 8-bit library (PCRE_UTF8)
// (*UTF16) set UTF-16 mode: 16-bit library (PCRE_UTF16)
// (*UCP) set PCRE_UCP (use Unicode properties for \d etc)
option
: '(' '?' option_flags '-' option_flags ')'
| '(' '?' option_flags ')'
| '(' '?' '-' option_flags ')'
| '(' '*' 'N' 'O' '_' 'S' 'T' 'A' 'R' 'T' '_' 'O' 'P' 'T' ')'
| '(' '*' 'U' 'T' 'F' '8' ')'
| '(' '*' 'U' 'T' 'F' '1' '6' ')'
| '(' '*' 'U' 'C' 'P' ')'
;
option_flags
: option_flag+
;
option_flag
: 'i'
| 'J'
| 'm'
| 's'
| 'U'
| 'x'
;
// LOOKAHEAD AND LOOKBEHIND ASSERTIONS
//
// (?=...) positive look ahead
// (?!...) negative look ahead
// (?<=...) positive look behind
// (?<!...) negative look behind
//
// Each top-level branch of a look behind must be of a fixed length.
look_around
: '(' '?' '=' alternation ')'
| '(' '?' '!' alternation ')'
| '(' '?' '<' '=' alternation ')'
| '(' '?' '<' '!' alternation ')'
;
// SUBROUTINE REFERENCES (POSSIBLY RECURSIVE)
//
// (?R) recurse whole pattern
// (?n) call subpattern by absolute number
// (?+n) call subpattern by relative number
// (?-n) call subpattern by relative number
// (?&name) call subpattern by name (Perl)
// (?P>name) call subpattern by name (Python)
// \g<name> call subpattern by name (Oniguruma)
// \g'name' call subpattern by name (Oniguruma)
// \g<n> call subpattern by absolute number (Oniguruma)
// \g'n' call subpattern by absolute number (Oniguruma)
// \g<+n> call subpattern by relative number (PCRE extension)
// \g'+n' call subpattern by relative number (PCRE extension)
// \g<-n> call subpattern by relative number (PCRE extension)
// \g'-n' call subpattern by relative number (PCRE extension)
subroutine_reference
: '(' '?' 'R' ')'
| '(' '?' number ')'
| '(' '?' '+' number ')'
| '(' '?' '-' number ')'
| '(' '?' '&' name ')'
| '(' '?' 'P' '>' name ')'
| '\\g' '<' name '>'
| '\\g' '\'' name '\''
| '\\g' '<' number '>'
| '\\g' '\'' number '\''
| '\\g' '<' '+' number '>'
| '\\g' '\'' '+' number '\''
| '\\g' '<' '-' number '>'
| '\\g' '\'' '-' number '\''
;
// CONDITIONAL PATTERNS
//
// (?(condition)yes-pattern)
// (?(condition)yes-pattern|no-pattern)
//
// (?(n)... absolute reference condition
// (?(+n)... relative reference condition
// (?(-n)... relative reference condition
// (?(<name>)... named reference condition (Perl)
// (?('name')... named reference condition (Perl)
// (?(name)... named reference condition (PCRE)
// (?(R)... overall recursion condition
// (?(Rn)... specific group recursion condition
// (?(R&name)... specific recursion condition
// (?(DEFINE)... define subpattern for reference
// (?(assert)... assertion condition
conditional
: '(' '?' '(' number ')' alternation ('|' alternation)? ')'
| '(' '?' '(' '+' number ')' alternation ('|' alternation)? ')'
| '(' '?' '(' '-' number ')' alternation ('|' alternation)? ')'
| '(' '?' '(' '<' name '>' ')' alternation ('|' alternation)? ')'
| '(' '?' '(' '\'' name '\'' ')' alternation ('|' alternation)? ')'
| '(' '?' '(' 'R' number ')' alternation ('|' alternation)? ')'
| '(' '?' '(' 'R' ')' alternation ('|' alternation)? ')'
| '(' '?' '(' 'R' '&' name ')' alternation ('|' alternation)? ')'
| '(' '?' '(' 'D' 'E' 'F' 'I' 'N' 'E' ')' alternation ('|' alternation)? ')'
| '(' '?' '(' 'a' 's' 's' 'e' 'r' 't' ')' alternation ('|' alternation)? ')'
| '(' '?' '(' name ')' alternation ('|' alternation)? ')'
;
// BACKTRACKING CONTROL
//
// The following act immediately they are reached:
//
// (*ACCEPT) force successful match
// (*FAIL) force backtrack; synonym (*F)
// (*MARK:NAME) set name to be passed back; synonym (*:NAME)
//
// The following act only when a subsequent match failure causes a back-
// track to reach them. They all force a match failure, but they differ in
// what happens afterwards. Those that advance the start-of-match point do
// so only if the pattern is not anchored.
//
// (*COMMIT) overall failure, no advance of starting point
// (*PRUNE) advance to next starting character
// (*PRUNE:NAME) equivalent to (*MARK:NAME)(*PRUNE)
// (*SKIP) advance to current matching position
// (*SKIP:NAME) advance to position corresponding to an earlier
// (*MARK:NAME); if not found, the (*SKIP) is ignored
// (*THEN) local failure, backtrack to next alternation
// (*THEN:NAME) equivalent to (*MARK:NAME)(*THEN)
backtrack_control
: '(' '*' 'A' 'C' 'C' 'E' 'P' 'T' ')'
| '(' '*' 'F' ('A' 'I' 'L')? ')'
| '(' '*' ('M' 'A' 'R' 'K')? ':' 'N' 'A' 'M' 'E' ')'
| '(' '*' 'C' 'O' 'M' 'M' 'I' 'T' ')'
| '(' '*' 'P' 'R' 'U' 'N' 'E' ')'
| '(' '*' 'P' 'R' 'U' 'N' 'E' ':' 'N' 'A' 'M' 'E' ')'
| '(' '*' 'S' 'K' 'I' 'P' ')'
| '(' '*' 'S' 'K' 'I' 'P' ':' 'N' 'A' 'M' 'E' ')'
| '(' '*' 'T' 'H' 'E' 'N' ')'
| '(' '*' 'T' 'H' 'E' 'N' ':' 'N' 'A' 'M' 'E' ')'
;
// NEWLINE CONVENTIONS
//capture
// These are recognized only at the very start of the pattern or after a
// (*BSR_...), (*UTF8), (*UTF16) or (*UCP) option.
//
// (*CR) carriage return only
// (*LF) linefeed only
// (*CRLF) carriage return followed by linefeed
// (*ANYCRLF) all three of the above
// (*ANY) any Unicode newline sequence
//
// WHAT \R MATCHES
//
// These are recognized only at the very start of the pattern or after a
// (*...) option that sets the newline convention or a UTF or UCP mode.
//
// (*BSR_ANYCRLF) CR, LF, or CRLF
// (*BSR_UNICODE) any Unicode newline sequence
newline_convention
: '(' '*' 'C' 'R' ')'
| '(' '*' 'L' 'F' ')'
| '(' '*' 'C' 'R' 'L' 'F' ')'
| '(' '*' 'A' 'N' 'Y' 'C' 'R' 'L' 'F' ')'
| '(' '*' 'A' 'N' 'Y' ')'
| '(' '*' 'B' 'S' 'R' '_' 'A' 'N' 'Y' 'C' 'R' 'L' 'F' ')'
| '(' '*' 'B' 'S' 'R' '_' 'U' 'N' 'I' 'C' 'O' 'D' 'E' ')'
;
// CALLOUTS
//
// (?C) callout
// (?Cn) callout with data n
callout
: '(' '?' 'C' ')'
| '(' '?' 'C' number ')'
;
atom
: subroutine_reference
| shared_atom
| literal
| character_class
| capture
| non_capture
| comment
| option
| look_around
| backreference
| conditional
| backtrack_control
| newline_convention
| callout
| Dot
| Caret
| StartOfSubject
| WordBoundary
| NonWordBoundary
| EndOfSubjectOrLine
| EndOfSubjectOrLineEndOfSubject
| EndOfSubject
| PreviousMatchInSubject
| ResetStartMatch
| OneDataUnit
| ExtendedUnicodeChar
;
cc_atom
: cc_literal Hyphen cc_literal
| shared_atom
| cc_literal
| backreference_or_octal // only octal is valid in a cc
;
shared_atom
: POSIXNamedSet
| POSIXNegatedNamedSet
| ControlChar
| DecimalDigit
| NotDecimalDigit
| HorizontalWhiteSpace
| NotHorizontalWhiteSpace
| NotNewLine
| CharWithProperty
| CharWithoutProperty
| NewLineSequence
| WhiteSpace
| NotWhiteSpace
| VerticalWhiteSpace
| NotVerticalWhiteSpace
| WordChar
| NotWordChar
| Backslash . // will match "unfinished" escape sequences, like `\x`
;
literal
: shared_literal
| CharacterClassEnd
;
cc_literal
: shared_literal
| Dot
| CharacterClassStart
| Caret
| QuestionMark
| Plus
| Star
| WordBoundary
| EndOfSubjectOrLine
| Pipe
| OpenParen
| CloseParen
;
shared_literal
: octal_char
| letter
| digit
| BellChar
| EscapeChar
| FormFeed
| NewLine
| CarriageReturn
| Tab
| HexChar
| Quoted
| BlockQuoted
| OpenBrace
| CloseBrace
| Comma
| Hyphen
| LessThan
| GreaterThan
| SingleQuote
| Underscore
| Colon
| Hash
| Equals
| Exclamation
| Ampersand
| OtherChar
;
number
: digits
;
octal_char
: ( Backslash (D0 | D1 | D2 | D3) octal_digit octal_digit
| Backslash octal_digit octal_digit
)
;
octal_digit
: D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7
;
digits
: digit+
;
digit
: D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9
;
name
: alpha_nums
;
alpha_nums
: (letter | Underscore) (letter | Underscore | digit)*
;
non_close_parens
: non_close_paren+
;
non_close_paren
: ~CloseParen
;
letter
: ALC | BLC | CLC | DLC | ELC | FLC | GLC | HLC | ILC | JLC | KLC | LLC | MLC | NLC | OLC | PLC | QLC | RLC | SLC | TLC | ULC | VLC | WLC | XLC | YLC | ZLC |
AUC | BUC | CUC | DUC | EUC | FUC | GUC | HUC | IUC | JUC | KUC | LUC | MUC | NUC | OUC | PUC | QUC | RUC | SUC | TUC | UUC | VUC | WUC | XUC | YUC | ZUC
;
// QUOTING
//
// \x where x is non-alphanumeric is a literal x
// \Q...\E treat enclosed characters as literal
Quoted : '\\' NonAlphaNumeric;
BlockQuoted : '\\Q' .*? '\\E';
// CHARACTERS
//
// \a alarm, that is, the BEL character (hex 07)
// \cx "control-x", where x is any ASCII character
// \e escape (hex 1B)
// \f form feed (hex 0C)
// \n newline (hex 0A)
// \r carriage return (hex 0D)
// \t tab (hex 09)
// \ddd character with octal code ddd, or backreference
// \xhh character with hex code hh
// \x{hhh..} character with hex code hhh..
BellChar : '\\a';
ControlChar : '\\c' ASCII?;
EscapeChar : '\\e';
FormFeed : '\\f';
NewLine : '\\n';
CarriageReturn : '\\r';
Tab : '\\t';
Backslash : '\\';
HexChar : '\\x' ( HexDigit HexDigit
| '{' HexDigit HexDigit HexDigit+ '}'
)
;
// CHARACTER TYPES
//
// . any character except newline;
// in dotall mode, any character whatsoever
// \C one data unit, even in UTF mode (best avoided)
// \d a decimal digit
// \D a character that is not a decimal digit
// \h a horizontal white space character
// \H a character that is not a horizontal white space character
// \N a character that is not a newline
// \p{xx} a character with the xx property
// \P{xx} a character without the xx property
// \R a newline sequence
// \s a white space character
// \S a character that is not a white space character
// \v a vertical white space character
// \V a character that is not a vertical white space character
// \w a "word" character
// \W a "non-word" character
// \X an extended Unicode sequence
//
// In PCRE, by default, \d, \D, \s, \S, \w, and \W recognize only ASCII
// characters, even in a UTF mode. However, this can be changed by setting
// the PCRE_UCP option.
Dot : '.';
OneDataUnit : '\\C';
DecimalDigit : '\\d';
NotDecimalDigit : '\\D';
HorizontalWhiteSpace : '\\h';
NotHorizontalWhiteSpace : '\\H';
NotNewLine : '\\N';
CharWithProperty : '\\p{' UnderscoreAlphaNumerics '}';
CharWithoutProperty : '\\P{' UnderscoreAlphaNumerics '}';
NewLineSequence : '\\R';
WhiteSpace : '\\s';
NotWhiteSpace : '\\S';
VerticalWhiteSpace : '\\v';
NotVerticalWhiteSpace : '\\V';
WordChar : '\\w';
NotWordChar : '\\W';
ExtendedUnicodeChar : '\\X';
// CHARACTER CLASSES
//
// [...] positive character class
// [^...] negative character class
// [x-y] range (can be used for hex characters)
// [[:xxx:]] positive POSIX named set
// [[:^xxx:]] negative POSIX named set
//
// alnum alphanumeric
// alpha alphabetic
// ascii 0-127
// blank space or tab
// cntrl control character
// digit decimal digit
// graph printing, excluding space
// lower lower case letter
// print printing, including space
// punct printing, excluding alphanumeric
// space white space
// upper upper case letter
// word same as \w
// xdigit hexadecimal digit
//
// In PCRE, POSIX character set names recognize only ASCII characters by
// default, but some of them use Unicode properties if PCRE_UCP is set.
// You can use \Q...\E inside a character class.
CharacterClassStart : '[';
CharacterClassEnd : ']';
Caret : '^';
Hyphen : '-';
POSIXNamedSet : '[[:' AlphaNumerics ':]]';
POSIXNegatedNamedSet : '[[:^' AlphaNumerics ':]]';
QuestionMark : '?';
Plus : '+';
Star : '*';
OpenBrace : '{';
CloseBrace : '}';
Comma : ',';
// ANCHORS AND SIMPLE ASSERTIONS
//
// \b word boundary
// \B not a word boundary
// ^ start of subject
// also after internal newline in multiline mode
// \A start of subject
// $ end of subject
// also before newline at end of subject
// also before internal newline in multiline mode
// \Z end of subject
// also before newline at end of subject
// \z end of subject
// \G first matching position in subject
WordBoundary : '\\b';
NonWordBoundary : '\\B';
StartOfSubject : '\\A';
EndOfSubjectOrLine : '$';
EndOfSubjectOrLineEndOfSubject : '\\Z';
EndOfSubject : '\\z';
PreviousMatchInSubject : '\\G';
// MATCH POINT RESET
//
// \K reset start of match
ResetStartMatch : '\\K';
SubroutineOrNamedReferenceStartG : '\\g';
NamedReferenceStartK : '\\k';
Pipe : '|';
OpenParen : '(';
CloseParen : ')';
LessThan : '<';
GreaterThan : '>';
SingleQuote : '\'';
Underscore : '_';
Colon : ':';
Hash : '#';
Equals : '=';
Exclamation : '!';
Ampersand : '&';
ALC : 'a';
BLC : 'b';
CLC : 'c';
DLC : 'd';
ELC : 'e';
FLC : 'f';
GLC : 'g';
HLC : 'h';
ILC : 'i';
JLC : 'j';
KLC : 'k';
LLC : 'l';
MLC : 'm';
NLC : 'n';
OLC : 'o';
PLC : 'p';
QLC : 'q';
RLC : 'r';
SLC : 's';
TLC : 't';
ULC : 'u';
VLC : 'v';
WLC : 'w';
XLC : 'x';
YLC : 'y';
ZLC : 'z';
AUC : 'A';
BUC : 'B';
CUC : 'C';
DUC : 'D';
EUC : 'E';
FUC : 'F';
GUC : 'G';
HUC : 'H';
IUC : 'I';
JUC : 'J';
KUC : 'K';
LUC : 'L';
MUC : 'M';
NUC : 'N';
OUC : 'O';
PUC : 'P';
QUC : 'Q';
RUC : 'R';
SUC : 'S';
TUC : 'T';
UUC : 'U';
VUC : 'V';
WUC : 'W';
XUC : 'X';
YUC : 'Y';
ZUC : 'Z';
D1 : '1';
D2 : '2';
D3 : '3';
D4 : '4';
D5 : '5';
D6 : '6';
D7 : '7';
D8 : '8';
D9 : '9';
D0 : '0';
OtherChar : . ;
// fragments
fragment UnderscoreAlphaNumerics : ('_' | AlphaNumeric)+;
fragment AlphaNumerics : AlphaNumeric+;
fragment AlphaNumeric : [a-zA-Z0-9];
fragment NonAlphaNumeric : ~[a-zA-Z0-9];
fragment HexDigit : [0-9a-fA-F];
fragment ASCII : [\u0000-\u007F];

View File

@ -0,0 +1,35 @@
package ru.touchin.roboswag.textprocessing
import android.widget.EditText
import ru.touchin.roboswag.textprocessing.generators.DecoroMaskGenerator
import ru.touchin.roboswag.textprocessing.generators.PlaceholderGenerator
import ru.touchin.roboswag.textprocessing.generators.regexgenerator.RegexReplaceGenerator
class TextFormatter(private val regex: String) {
private val regexReplaceGenerator = RegexReplaceGenerator()
private val decoroMaskGenerator = DecoroMaskGenerator()
private val pcreGeneratorItem = regexReplaceGenerator.regexToRegexReplace(regex)
private val regexReplaceString = pcreGeneratorItem.regexReplaceString
private val matrixOfSymbols = pcreGeneratorItem.matrixOfSymbols
private val placeholderGenerator = PlaceholderGenerator(matrixOfSymbols)
fun getFormattedText(inputText: String) = inputText.replace(Regex(regex), regexReplaceString)
fun getPlaceholder() = placeholderGenerator.placeholder
fun getRegexReplace() = regexReplaceString
fun mask(editText: EditText) {
val formatWatcher = decoroMaskGenerator.mask(
placeholderGenerator.placeholder,
matrixOfSymbols
)
formatWatcher.installOn(editText)
}
}

View File

@ -0,0 +1,24 @@
package ru.touchin.roboswag.textprocessing.generators
import ru.tinkoff.decoro.MaskImpl
import ru.tinkoff.decoro.slots.PredefinedSlots
import ru.tinkoff.decoro.slots.Slot
import ru.tinkoff.decoro.watchers.MaskFormatWatcher
import ru.touchin.roboswag.textprocessing.validators.CustomValidator
class DecoroMaskGenerator {
/** Генерация маски и слотов на основе возможных символов для placeholder,
* если возможный символ всего один, то символ хардкодится в слот
* **/
fun mask(placeholder: String, matrixOfSymbols: Matrix<Char>): MaskFormatWatcher {
val slots = placeholder.mapIndexed { index, char ->
if (matrixOfSymbols[index].size == 1) {
PredefinedSlots.hardcodedSlot(char)
} else {
CustomValidator.customSlot(matrixOfSymbols[index])
}
}
return MaskFormatWatcher(MaskImpl.createTerminated(slots.toTypedArray()))
}
}

View File

@ -0,0 +1,3 @@
package ru.touchin.roboswag.textprocessing.generators
typealias Matrix<T> = List<List<T>>

View File

@ -0,0 +1,30 @@
package ru.touchin.roboswag.textprocessing.generators
class PlaceholderGenerator(matrixOfSymbols: Matrix<Char>) {
val placeholder = generatePlaceholder(matrixOfSymbols)
private fun generatePlaceholder(matrixOfSymbols: Matrix<Char>): String {
val placeholderStringBuilder = StringBuilder()
val indexes = hashMapOf<List<Char>, Int>()
for (listOfSymbols in matrixOfSymbols) {
indexes[listOfSymbols] = 0
}
for (listOfSymbols in matrixOfSymbols) {
if (listOfSymbols.isEmpty()) continue
/** Если элемент без повторений **/
if (listOfSymbols.size == 1) {
placeholderStringBuilder.append(listOfSymbols[0])
continue
}
indexes[listOfSymbols]?.let {
var index = it
if (listOfSymbols.size <= index) index = 0
placeholderStringBuilder.append(listOfSymbols[index])
index++
indexes[listOfSymbols] = index
}
}
return placeholderStringBuilder.toString()
}
}

View File

@ -0,0 +1,8 @@
package ru.touchin.roboswag.textprocessing.generators.regexgenerator
import ru.touchin.roboswag.textprocessing.generators.Matrix
class PCREGeneratorItem(
val regexReplaceString: String,
val matrixOfSymbols: Matrix<Char>
)

View File

@ -0,0 +1,106 @@
package ru.touchin.roboswag.textprocessing.generators.regexgenerator
import ru.touchin.roboswag.textprocessing.pcre.parser.PCREBaseListener
import ru.touchin.roboswag.textprocessing.pcre.parser.PCREParser
class PCREGeneratorListener : PCREBaseListener() {
/**
* Лист для placeholder, где индекс - номер буквы для placeholder
* значение - возможные символы для placeholder
* **/
private val matrixOfSymbols = mutableListOf<List<Char>>()
private var currentGroupIndex = 1
private var regexReplaceString = ""
/** Элемент поиска с регулярного выражения
* В себе может содержать возможные элементы регулярного выражения,
* например:
* [1-2], \\d, [A-B], а так же элементы не относящиеся к регулярным выражениям
* или экранизированые
* **/
private var listOfSymbols = mutableListOf<Char>()
override fun enterCapture(ctx: PCREParser.CaptureContext) {
super.enterCapture(ctx)
regexReplaceString += "\$$currentGroupIndex"
currentGroupIndex++
}
override fun enterShared_atom(ctx: PCREParser.Shared_atomContext) {
super.enterShared_atom(ctx)
/** Найдено соответствие цифр \\d **/
listOfSymbols = '1'.rangeTo('9').toMutableList().apply { add('0') }
matrixOfSymbols.add(listOfSymbols)
}
override fun enterCharacter_class(ctx: PCREParser.Character_classContext) {
super.enterCharacter_class(ctx)
/** Проверка на количество диапазонов
* true - если, например [А-дD-f]
* false - если, например [А-д]
* **/
if (ctx.cc_atom().size > 1) {
listOfSymbols = mutableListOf<Char>()
val firstChar = ctx.CharacterClassStart().text
val endChar = ctx.CharacterClassEnd()[0].text
for (i in 0 until ctx.cc_atom().size) {
listOfSymbols += availableSymbolsToList(firstChar + ctx.cc_atom()[i].text + endChar)
}
} else {
listOfSymbols = availableSymbolsToList(ctx.text)
}
matrixOfSymbols.add(listOfSymbols)
}
/** Дублирование повторений для placeholder при их наличии, например [A-B]{6}, где 6 - повторения **/
override fun enterDigits(ctx: PCREParser.DigitsContext) {
super.enterDigits(ctx)
repeat(ctx.text.toInt() - 1) {
matrixOfSymbols.add(listOfSymbols)
}
}
override fun enterLiteral(ctx: PCREParser.LiteralContext) {
super.enterLiteral(ctx)
regexReplaceString += ctx.shared_literal().text
listOfSymbols = mutableListOf<Char>()
for (s in ctx.text) {
listOfSymbols.add(s)
}
matrixOfSymbols.add(listOfSymbols)
}
fun toPCREGeneratorItem() = PCREGeneratorItem(
regexReplaceString,
matrixOfSymbols.map { chars ->
chars.filter {
it != '\\'
}
}
)
private fun availableSymbolsToList(ctxText: String): MutableList<Char> {
/** startAtomStr = atomStr[1] - потому что должен проверяться первый допуск для строки
* endAtomStr index of atomStr.length - 2 вычисляется потому что с поиском,
* например, [A-B], endAtomStr = "B", startAtomStr = "A"
* **/
val endAtomStr = ctxText[ctxText.length - 2]
val startAtomStr = ctxText[1]
return if (startAtomStr.isLetterOrDigit() && endAtomStr.isLetterOrDigit()) {
getListRangeChars(ctxText).filter {
it.isLetterOrDigit()
}.toMutableList()
} else {
mutableListOf(startAtomStr, endAtomStr)
}
}
private fun getListRangeChars(atomStr: String): MutableList<Char> {
val startRange = atomStr[1]
val endRange = atomStr[atomStr.length - 2]
return startRange.rangeTo(endRange).toMutableList()
}
}

View File

@ -0,0 +1,27 @@
package ru.touchin.roboswag.textprocessing.generators.regexgenerator
import org.antlr.v4.runtime.CharStreams
import org.antlr.v4.runtime.CommonTokenStream
import org.antlr.v4.runtime.tree.ParseTreeWalker
import ru.touchin.roboswag.textprocessing.pcre.parser.PCRELexer
import ru.touchin.roboswag.textprocessing.pcre.parser.PCREParser
class RegexReplaceGenerator {
fun regexToRegexReplace(regex: String): PCREGeneratorItem {
val stringStream = CharStreams.fromString(regex)
val lexer = PCRELexer(stringStream)
val parser = PCREParser(CommonTokenStream(lexer))
val parseContext = parser.parse()
val walker = ParseTreeWalker()
val pcreGeneratorListener = PCREGeneratorListener()
walker.walk(pcreGeneratorListener, parseContext)
return pcreGeneratorListener.toPCREGeneratorItem()
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,482 @@
package ru.touchin.roboswag.textprocessing.pcre.parser;
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 PCREListener},
* which can be extended to create a listener which only needs to handle a subset
* of the available methods.
*/
public class PCREBaseListener implements PCREListener {
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterParse(PCREParser.ParseContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitParse(PCREParser.ParseContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterAlternation(PCREParser.AlternationContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitAlternation(PCREParser.AlternationContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterExpr(PCREParser.ExprContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitExpr(PCREParser.ExprContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterElement(PCREParser.ElementContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitElement(PCREParser.ElementContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterQuantifier(PCREParser.QuantifierContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitQuantifier(PCREParser.QuantifierContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterQuantifier_type(PCREParser.Quantifier_typeContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitQuantifier_type(PCREParser.Quantifier_typeContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterCharacter_class(PCREParser.Character_classContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitCharacter_class(PCREParser.Character_classContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterBackreference(PCREParser.BackreferenceContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitBackreference(PCREParser.BackreferenceContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterBackreference_or_octal(PCREParser.Backreference_or_octalContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitBackreference_or_octal(PCREParser.Backreference_or_octalContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterCapture(PCREParser.CaptureContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitCapture(PCREParser.CaptureContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterNon_capture(PCREParser.Non_captureContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitNon_capture(PCREParser.Non_captureContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterComment(PCREParser.CommentContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitComment(PCREParser.CommentContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterOption(PCREParser.OptionContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitOption(PCREParser.OptionContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterOption_flags(PCREParser.Option_flagsContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitOption_flags(PCREParser.Option_flagsContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterOption_flag(PCREParser.Option_flagContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitOption_flag(PCREParser.Option_flagContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterLook_around(PCREParser.Look_aroundContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitLook_around(PCREParser.Look_aroundContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterSubroutine_reference(PCREParser.Subroutine_referenceContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitSubroutine_reference(PCREParser.Subroutine_referenceContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterConditional(PCREParser.ConditionalContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitConditional(PCREParser.ConditionalContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterBacktrack_control(PCREParser.Backtrack_controlContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitBacktrack_control(PCREParser.Backtrack_controlContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterNewline_convention(PCREParser.Newline_conventionContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitNewline_convention(PCREParser.Newline_conventionContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterCallout(PCREParser.CalloutContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitCallout(PCREParser.CalloutContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterAtom(PCREParser.AtomContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitAtom(PCREParser.AtomContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterCc_atom(PCREParser.Cc_atomContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitCc_atom(PCREParser.Cc_atomContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterShared_atom(PCREParser.Shared_atomContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitShared_atom(PCREParser.Shared_atomContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterLiteral(PCREParser.LiteralContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitLiteral(PCREParser.LiteralContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterCc_literal(PCREParser.Cc_literalContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitCc_literal(PCREParser.Cc_literalContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterShared_literal(PCREParser.Shared_literalContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitShared_literal(PCREParser.Shared_literalContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterNumber(PCREParser.NumberContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitNumber(PCREParser.NumberContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterOctal_char(PCREParser.Octal_charContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitOctal_char(PCREParser.Octal_charContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterOctal_digit(PCREParser.Octal_digitContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitOctal_digit(PCREParser.Octal_digitContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterDigits(PCREParser.DigitsContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitDigits(PCREParser.DigitsContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterDigit(PCREParser.DigitContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitDigit(PCREParser.DigitContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterName(PCREParser.NameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitName(PCREParser.NameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterAlpha_nums(PCREParser.Alpha_numsContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitAlpha_nums(PCREParser.Alpha_numsContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterNon_close_parens(PCREParser.Non_close_parensContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitNon_close_parens(PCREParser.Non_close_parensContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterNon_close_paren(PCREParser.Non_close_parenContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitNon_close_paren(PCREParser.Non_close_parenContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterLetter(PCREParser.LetterContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitLetter(PCREParser.LetterContext 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,272 @@
package ru.touchin.roboswag.textprocessing.pcre.parser;
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
/**
* This class provides an empty implementation of {@link PCREVisitor},
* which can be extended to create a visitor which only needs to handle a subset
* of the available methods.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public class PCREBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements PCREVisitor<T> {
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitParse(PCREParser.ParseContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAlternation(PCREParser.AlternationContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExpr(PCREParser.ExprContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitElement(PCREParser.ElementContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitQuantifier(PCREParser.QuantifierContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitQuantifier_type(PCREParser.Quantifier_typeContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitCharacter_class(PCREParser.Character_classContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitBackreference(PCREParser.BackreferenceContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitBackreference_or_octal(PCREParser.Backreference_or_octalContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitCapture(PCREParser.CaptureContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNon_capture(PCREParser.Non_captureContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitComment(PCREParser.CommentContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitOption(PCREParser.OptionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitOption_flags(PCREParser.Option_flagsContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitOption_flag(PCREParser.Option_flagContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLook_around(PCREParser.Look_aroundContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitSubroutine_reference(PCREParser.Subroutine_referenceContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitConditional(PCREParser.ConditionalContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitBacktrack_control(PCREParser.Backtrack_controlContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNewline_convention(PCREParser.Newline_conventionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitCallout(PCREParser.CalloutContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAtom(PCREParser.AtomContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitCc_atom(PCREParser.Cc_atomContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitShared_atom(PCREParser.Shared_atomContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLiteral(PCREParser.LiteralContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitCc_literal(PCREParser.Cc_literalContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitShared_literal(PCREParser.Shared_literalContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNumber(PCREParser.NumberContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitOctal_char(PCREParser.Octal_charContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitOctal_digit(PCREParser.Octal_digitContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitDigits(PCREParser.DigitsContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitDigit(PCREParser.DigitContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitName(PCREParser.NameContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAlpha_nums(PCREParser.Alpha_numsContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNon_close_parens(PCREParser.Non_close_parensContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNon_close_paren(PCREParser.Non_close_parenContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLetter(PCREParser.LetterContext ctx) { return visitChildren(ctx); }
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,386 @@
package ru.touchin.roboswag.textprocessing.pcre.parser;
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"})
public class PCRELexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.9.2", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
public static final int
Quoted=1, BlockQuoted=2, BellChar=3, ControlChar=4, EscapeChar=5, FormFeed=6,
NewLine=7, CarriageReturn=8, Tab=9, Backslash=10, HexChar=11, Dot=12,
OneDataUnit=13, DecimalDigit=14, NotDecimalDigit=15, HorizontalWhiteSpace=16,
NotHorizontalWhiteSpace=17, NotNewLine=18, CharWithProperty=19, CharWithoutProperty=20,
NewLineSequence=21, WhiteSpace=22, NotWhiteSpace=23, VerticalWhiteSpace=24,
NotVerticalWhiteSpace=25, WordChar=26, NotWordChar=27, ExtendedUnicodeChar=28,
CharacterClassStart=29, CharacterClassEnd=30, Caret=31, Hyphen=32, POSIXNamedSet=33,
POSIXNegatedNamedSet=34, QuestionMark=35, Plus=36, Star=37, OpenBrace=38,
CloseBrace=39, Comma=40, WordBoundary=41, NonWordBoundary=42, StartOfSubject=43,
EndOfSubjectOrLine=44, EndOfSubjectOrLineEndOfSubject=45, EndOfSubject=46,
PreviousMatchInSubject=47, ResetStartMatch=48, SubroutineOrNamedReferenceStartG=49,
NamedReferenceStartK=50, Pipe=51, OpenParen=52, CloseParen=53, LessThan=54,
GreaterThan=55, SingleQuote=56, Underscore=57, Colon=58, Hash=59, Equals=60,
Exclamation=61, Ampersand=62, ALC=63, BLC=64, CLC=65, DLC=66, ELC=67,
FLC=68, GLC=69, HLC=70, ILC=71, JLC=72, KLC=73, LLC=74, MLC=75, NLC=76,
OLC=77, PLC=78, QLC=79, RLC=80, SLC=81, TLC=82, ULC=83, VLC=84, WLC=85,
XLC=86, YLC=87, ZLC=88, AUC=89, BUC=90, CUC=91, DUC=92, EUC=93, FUC=94,
GUC=95, HUC=96, IUC=97, JUC=98, KUC=99, LUC=100, MUC=101, NUC=102, OUC=103,
PUC=104, QUC=105, RUC=106, SUC=107, TUC=108, UUC=109, VUC=110, WUC=111,
XUC=112, YUC=113, ZUC=114, D1=115, D2=116, D3=117, D4=118, D5=119, D6=120,
D7=121, D8=122, D9=123, D0=124, OtherChar=125;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
public static String[] modeNames = {
"DEFAULT_MODE"
};
private static String[] makeRuleNames() {
return new String[] {
"Quoted", "BlockQuoted", "BellChar", "ControlChar", "EscapeChar", "FormFeed",
"NewLine", "CarriageReturn", "Tab", "Backslash", "HexChar", "Dot", "OneDataUnit",
"DecimalDigit", "NotDecimalDigit", "HorizontalWhiteSpace", "NotHorizontalWhiteSpace",
"NotNewLine", "CharWithProperty", "CharWithoutProperty", "NewLineSequence",
"WhiteSpace", "NotWhiteSpace", "VerticalWhiteSpace", "NotVerticalWhiteSpace",
"WordChar", "NotWordChar", "ExtendedUnicodeChar", "CharacterClassStart",
"CharacterClassEnd", "Caret", "Hyphen", "POSIXNamedSet", "POSIXNegatedNamedSet",
"QuestionMark", "Plus", "Star", "OpenBrace", "CloseBrace", "Comma", "WordBoundary",
"NonWordBoundary", "StartOfSubject", "EndOfSubjectOrLine", "EndOfSubjectOrLineEndOfSubject",
"EndOfSubject", "PreviousMatchInSubject", "ResetStartMatch", "SubroutineOrNamedReferenceStartG",
"NamedReferenceStartK", "Pipe", "OpenParen", "CloseParen", "LessThan",
"GreaterThan", "SingleQuote", "Underscore", "Colon", "Hash", "Equals",
"Exclamation", "Ampersand", "ALC", "BLC", "CLC", "DLC", "ELC", "FLC",
"GLC", "HLC", "ILC", "JLC", "KLC", "LLC", "MLC", "NLC", "OLC", "PLC",
"QLC", "RLC", "SLC", "TLC", "ULC", "VLC", "WLC", "XLC", "YLC", "ZLC",
"AUC", "BUC", "CUC", "DUC", "EUC", "FUC", "GUC", "HUC", "IUC", "JUC",
"KUC", "LUC", "MUC", "NUC", "OUC", "PUC", "QUC", "RUC", "SUC", "TUC",
"UUC", "VUC", "WUC", "XUC", "YUC", "ZUC", "D1", "D2", "D3", "D4", "D5",
"D6", "D7", "D8", "D9", "D0", "OtherChar", "UnderscoreAlphaNumerics",
"AlphaNumerics", "AlphaNumeric", "NonAlphaNumeric", "HexDigit", "ASCII"
};
}
public static final String[] ruleNames = makeRuleNames();
private static String[] makeLiteralNames() {
return new String[] {
null, null, null, "'\\a'", null, "'\\e'", "'\\f'", "'\\n'", "'\\r'",
"'\\t'", "'\\'", null, "'.'", "'\\C'", "'\\d'", "'\\D'", "'\\h'", "'\\H'",
"'\\N'", null, null, "'\\R'", "'\\s'", "'\\S'", "'\\v'", "'\\V'", "'\\w'",
"'\\W'", "'\\X'", "'['", "']'", "'^'", "'-'", null, null, "'?'", "'+'",
"'*'", "'{'", "'}'", "','", "'\\b'", "'\\B'", "'\\A'", "'$'", "'\\Z'",
"'\\z'", "'\\G'", "'\\K'", "'\\g'", "'\\k'", "'|'", "'('", "')'", "'<'",
"'>'", "'''", "'_'", "':'", "'#'", "'='", "'!'", "'&'", "'a'", "'b'",
"'c'", "'d'", "'e'", "'f'", "'g'", "'h'", "'i'", "'j'", "'k'", "'l'",
"'m'", "'n'", "'o'", "'p'", "'q'", "'r'", "'s'", "'t'", "'u'", "'v'",
"'w'", "'x'", "'y'", "'z'", "'A'", "'B'", "'C'", "'D'", "'E'", "'F'",
"'G'", "'H'", "'I'", "'J'", "'K'", "'L'", "'M'", "'N'", "'O'", "'P'",
"'Q'", "'R'", "'S'", "'T'", "'U'", "'V'", "'W'", "'X'", "'Y'", "'Z'",
"'1'", "'2'", "'3'", "'4'", "'5'", "'6'", "'7'", "'8'", "'9'", "'0'"
};
}
private static final String[] _LITERAL_NAMES = makeLiteralNames();
private static String[] makeSymbolicNames() {
return new String[] {
null, "Quoted", "BlockQuoted", "BellChar", "ControlChar", "EscapeChar",
"FormFeed", "NewLine", "CarriageReturn", "Tab", "Backslash", "HexChar",
"Dot", "OneDataUnit", "DecimalDigit", "NotDecimalDigit", "HorizontalWhiteSpace",
"NotHorizontalWhiteSpace", "NotNewLine", "CharWithProperty", "CharWithoutProperty",
"NewLineSequence", "WhiteSpace", "NotWhiteSpace", "VerticalWhiteSpace",
"NotVerticalWhiteSpace", "WordChar", "NotWordChar", "ExtendedUnicodeChar",
"CharacterClassStart", "CharacterClassEnd", "Caret", "Hyphen", "POSIXNamedSet",
"POSIXNegatedNamedSet", "QuestionMark", "Plus", "Star", "OpenBrace",
"CloseBrace", "Comma", "WordBoundary", "NonWordBoundary", "StartOfSubject",
"EndOfSubjectOrLine", "EndOfSubjectOrLineEndOfSubject", "EndOfSubject",
"PreviousMatchInSubject", "ResetStartMatch", "SubroutineOrNamedReferenceStartG",
"NamedReferenceStartK", "Pipe", "OpenParen", "CloseParen", "LessThan",
"GreaterThan", "SingleQuote", "Underscore", "Colon", "Hash", "Equals",
"Exclamation", "Ampersand", "ALC", "BLC", "CLC", "DLC", "ELC", "FLC",
"GLC", "HLC", "ILC", "JLC", "KLC", "LLC", "MLC", "NLC", "OLC", "PLC",
"QLC", "RLC", "SLC", "TLC", "ULC", "VLC", "WLC", "XLC", "YLC", "ZLC",
"AUC", "BUC", "CUC", "DUC", "EUC", "FUC", "GUC", "HUC", "IUC", "JUC",
"KUC", "LUC", "MUC", "NUC", "OUC", "PUC", "QUC", "RUC", "SUC", "TUC",
"UUC", "VUC", "WUC", "XUC", "YUC", "ZUC", "D1", "D2", "D3", "D4", "D5",
"D6", "D7", "D8", "D9", "D0", "OtherChar"
};
}
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 PCRELexer(CharStream input) {
super(input);
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
@Override
public String getGrammarFileName() { return "PCRE.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 =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\177\u026b\b\1\4\2"+
"\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+
"\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+
"\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31"+
"\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t"+
" \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t"+
"+\4,\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64"+
"\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t"+
"=\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4"+
"I\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\t"+
"T\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_"+
"\4`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\ti\4j\tj\4k"+
"\tk\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\4q\tq\4r\tr\4s\ts\4t\tt\4u\tu\4v\tv"+
"\4w\tw\4x\tx\4y\ty\4z\tz\4{\t{\4|\t|\4}\t}\4~\t~\4\177\t\177\4\u0080\t"+
"\u0080\4\u0081\t\u0081\4\u0082\t\u0082\4\u0083\t\u0083\4\u0084\t\u0084"+
"\3\2\3\2\3\2\3\3\3\3\3\3\3\3\7\3\u0111\n\3\f\3\16\3\u0114\13\3\3\3\3\3"+
"\3\3\3\4\3\4\3\4\3\5\3\5\3\5\3\5\5\5\u0120\n\5\3\6\3\6\3\6\3\7\3\7\3\7"+
"\3\b\3\b\3\b\3\t\3\t\3\t\3\n\3\n\3\n\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f"+
"\3\f\3\f\3\f\3\f\6\f\u013d\n\f\r\f\16\f\u013e\3\f\3\f\5\f\u0143\n\f\3"+
"\r\3\r\3\16\3\16\3\16\3\17\3\17\3\17\3\20\3\20\3\20\3\21\3\21\3\21\3\22"+
"\3\22\3\22\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25"+
"\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\27\3\27\3\27\3\30\3\30\3\30"+
"\3\31\3\31\3\31\3\32\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\35\3\35"+
"\3\35\3\36\3\36\3\37\3\37\3 \3 \3!\3!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\""+
"\3\"\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3$\3$\3%\3%\3&\3&\3\'\3\'\3(\3(\3)"+
"\3)\3*\3*\3*\3+\3+\3+\3,\3,\3,\3-\3-\3.\3.\3.\3/\3/\3/\3\60\3\60\3\60"+
"\3\61\3\61\3\61\3\62\3\62\3\62\3\63\3\63\3\63\3\64\3\64\3\65\3\65\3\66"+
"\3\66\3\67\3\67\38\38\39\39\3:\3:\3;\3;\3<\3<\3=\3=\3>\3>\3?\3?\3@\3@"+
"\3A\3A\3B\3B\3C\3C\3D\3D\3E\3E\3F\3F\3G\3G\3H\3H\3I\3I\3J\3J\3K\3K\3L"+
"\3L\3M\3M\3N\3N\3O\3O\3P\3P\3Q\3Q\3R\3R\3S\3S\3T\3T\3U\3U\3V\3V\3W\3W"+
"\3X\3X\3Y\3Y\3Z\3Z\3[\3[\3\\\3\\\3]\3]\3^\3^\3_\3_\3`\3`\3a\3a\3b\3b\3"+
"c\3c\3d\3d\3e\3e\3f\3f\3g\3g\3h\3h\3i\3i\3j\3j\3k\3k\3l\3l\3m\3m\3n\3"+
"n\3o\3o\3p\3p\3q\3q\3r\3r\3s\3s\3t\3t\3u\3u\3v\3v\3w\3w\3x\3x\3y\3y\3"+
"z\3z\3{\3{\3|\3|\3}\3}\3~\3~\3\177\3\177\6\177\u025b\n\177\r\177\16\177"+
"\u025c\3\u0080\6\u0080\u0260\n\u0080\r\u0080\16\u0080\u0261\3\u0081\3"+
"\u0081\3\u0082\3\u0082\3\u0083\3\u0083\3\u0084\3\u0084\3\u0112\2\u0085"+
"\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20"+
"\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37"+
"= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o"+
"9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH"+
"\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1"+
"R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5"+
"\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9"+
"f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7m\u00d9n\u00dbo\u00dd"+
"p\u00dfq\u00e1r\u00e3s\u00e5t\u00e7u\u00e9v\u00ebw\u00edx\u00efy\u00f1"+
"z\u00f3{\u00f5|\u00f7}\u00f9~\u00fb\177\u00fd\2\u00ff\2\u0101\2\u0103"+
"\2\u0105\2\u0107\2\3\2\5\5\2\62;C\\c|\5\2\62;CHch\3\2\2\u0081\2\u026b"+
"\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2"+
"\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2"+
"\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2"+
"\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2"+
"\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3"+
"\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2"+
"\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2"+
"U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3"+
"\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2"+
"\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2"+
"{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085"+
"\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2"+
"\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097"+
"\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2"+
"\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9"+
"\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2"+
"\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb"+
"\3\2\2\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2"+
"\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd"+
"\3\2\2\2\2\u00cf\3\2\2\2\2\u00d1\3\2\2\2\2\u00d3\3\2\2\2\2\u00d5\3\2\2"+
"\2\2\u00d7\3\2\2\2\2\u00d9\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2\2\2\u00df"+
"\3\2\2\2\2\u00e1\3\2\2\2\2\u00e3\3\2\2\2\2\u00e5\3\2\2\2\2\u00e7\3\2\2"+
"\2\2\u00e9\3\2\2\2\2\u00eb\3\2\2\2\2\u00ed\3\2\2\2\2\u00ef\3\2\2\2\2\u00f1"+
"\3\2\2\2\2\u00f3\3\2\2\2\2\u00f5\3\2\2\2\2\u00f7\3\2\2\2\2\u00f9\3\2\2"+
"\2\2\u00fb\3\2\2\2\3\u0109\3\2\2\2\5\u010c\3\2\2\2\7\u0118\3\2\2\2\t\u011b"+
"\3\2\2\2\13\u0121\3\2\2\2\r\u0124\3\2\2\2\17\u0127\3\2\2\2\21\u012a\3"+
"\2\2\2\23\u012d\3\2\2\2\25\u0130\3\2\2\2\27\u0132\3\2\2\2\31\u0144\3\2"+
"\2\2\33\u0146\3\2\2\2\35\u0149\3\2\2\2\37\u014c\3\2\2\2!\u014f\3\2\2\2"+
"#\u0152\3\2\2\2%\u0155\3\2\2\2\'\u0158\3\2\2\2)\u015f\3\2\2\2+\u0166\3"+
"\2\2\2-\u0169\3\2\2\2/\u016c\3\2\2\2\61\u016f\3\2\2\2\63\u0172\3\2\2\2"+
"\65\u0175\3\2\2\2\67\u0178\3\2\2\29\u017b\3\2\2\2;\u017e\3\2\2\2=\u0180"+
"\3\2\2\2?\u0182\3\2\2\2A\u0184\3\2\2\2C\u0186\3\2\2\2E\u018f\3\2\2\2G"+
"\u0199\3\2\2\2I\u019b\3\2\2\2K\u019d\3\2\2\2M\u019f\3\2\2\2O\u01a1\3\2"+
"\2\2Q\u01a3\3\2\2\2S\u01a5\3\2\2\2U\u01a8\3\2\2\2W\u01ab\3\2\2\2Y\u01ae"+
"\3\2\2\2[\u01b0\3\2\2\2]\u01b3\3\2\2\2_\u01b6\3\2\2\2a\u01b9\3\2\2\2c"+
"\u01bc\3\2\2\2e\u01bf\3\2\2\2g\u01c2\3\2\2\2i\u01c4\3\2\2\2k\u01c6\3\2"+
"\2\2m\u01c8\3\2\2\2o\u01ca\3\2\2\2q\u01cc\3\2\2\2s\u01ce\3\2\2\2u\u01d0"+
"\3\2\2\2w\u01d2\3\2\2\2y\u01d4\3\2\2\2{\u01d6\3\2\2\2}\u01d8\3\2\2\2\177"+
"\u01da\3\2\2\2\u0081\u01dc\3\2\2\2\u0083\u01de\3\2\2\2\u0085\u01e0\3\2"+
"\2\2\u0087\u01e2\3\2\2\2\u0089\u01e4\3\2\2\2\u008b\u01e6\3\2\2\2\u008d"+
"\u01e8\3\2\2\2\u008f\u01ea\3\2\2\2\u0091\u01ec\3\2\2\2\u0093\u01ee\3\2"+
"\2\2\u0095\u01f0\3\2\2\2\u0097\u01f2\3\2\2\2\u0099\u01f4\3\2\2\2\u009b"+
"\u01f6\3\2\2\2\u009d\u01f8\3\2\2\2\u009f\u01fa\3\2\2\2\u00a1\u01fc\3\2"+
"\2\2\u00a3\u01fe\3\2\2\2\u00a5\u0200\3\2\2\2\u00a7\u0202\3\2\2\2\u00a9"+
"\u0204\3\2\2\2\u00ab\u0206\3\2\2\2\u00ad\u0208\3\2\2\2\u00af\u020a\3\2"+
"\2\2\u00b1\u020c\3\2\2\2\u00b3\u020e\3\2\2\2\u00b5\u0210\3\2\2\2\u00b7"+
"\u0212\3\2\2\2\u00b9\u0214\3\2\2\2\u00bb\u0216\3\2\2\2\u00bd\u0218\3\2"+
"\2\2\u00bf\u021a\3\2\2\2\u00c1\u021c\3\2\2\2\u00c3\u021e\3\2\2\2\u00c5"+
"\u0220\3\2\2\2\u00c7\u0222\3\2\2\2\u00c9\u0224\3\2\2\2\u00cb\u0226\3\2"+
"\2\2\u00cd\u0228\3\2\2\2\u00cf\u022a\3\2\2\2\u00d1\u022c\3\2\2\2\u00d3"+
"\u022e\3\2\2\2\u00d5\u0230\3\2\2\2\u00d7\u0232\3\2\2\2\u00d9\u0234\3\2"+
"\2\2\u00db\u0236\3\2\2\2\u00dd\u0238\3\2\2\2\u00df\u023a\3\2\2\2\u00e1"+
"\u023c\3\2\2\2\u00e3\u023e\3\2\2\2\u00e5\u0240\3\2\2\2\u00e7\u0242\3\2"+
"\2\2\u00e9\u0244\3\2\2\2\u00eb\u0246\3\2\2\2\u00ed\u0248\3\2\2\2\u00ef"+
"\u024a\3\2\2\2\u00f1\u024c\3\2\2\2\u00f3\u024e\3\2\2\2\u00f5\u0250\3\2"+
"\2\2\u00f7\u0252\3\2\2\2\u00f9\u0254\3\2\2\2\u00fb\u0256\3\2\2\2\u00fd"+
"\u025a\3\2\2\2\u00ff\u025f\3\2\2\2\u0101\u0263\3\2\2\2\u0103\u0265\3\2"+
"\2\2\u0105\u0267\3\2\2\2\u0107\u0269\3\2\2\2\u0109\u010a\7^\2\2\u010a"+
"\u010b\5\u0103\u0082\2\u010b\4\3\2\2\2\u010c\u010d\7^\2\2\u010d\u010e"+
"\7S\2\2\u010e\u0112\3\2\2\2\u010f\u0111\13\2\2\2\u0110\u010f\3\2\2\2\u0111"+
"\u0114\3\2\2\2\u0112\u0113\3\2\2\2\u0112\u0110\3\2\2\2\u0113\u0115\3\2"+
"\2\2\u0114\u0112\3\2\2\2\u0115\u0116\7^\2\2\u0116\u0117\7G\2\2\u0117\6"+
"\3\2\2\2\u0118\u0119\7^\2\2\u0119\u011a\7c\2\2\u011a\b\3\2\2\2\u011b\u011c"+
"\7^\2\2\u011c\u011d\7e\2\2\u011d\u011f\3\2\2\2\u011e\u0120\5\u0107\u0084"+
"\2\u011f\u011e\3\2\2\2\u011f\u0120\3\2\2\2\u0120\n\3\2\2\2\u0121\u0122"+
"\7^\2\2\u0122\u0123\7g\2\2\u0123\f\3\2\2\2\u0124\u0125\7^\2\2\u0125\u0126"+
"\7h\2\2\u0126\16\3\2\2\2\u0127\u0128\7^\2\2\u0128\u0129\7p\2\2\u0129\20"+
"\3\2\2\2\u012a\u012b\7^\2\2\u012b\u012c\7t\2\2\u012c\22\3\2\2\2\u012d"+
"\u012e\7^\2\2\u012e\u012f\7v\2\2\u012f\24\3\2\2\2\u0130\u0131\7^\2\2\u0131"+
"\26\3\2\2\2\u0132\u0133\7^\2\2\u0133\u0134\7z\2\2\u0134\u0142\3\2\2\2"+
"\u0135\u0136\5\u0105\u0083\2\u0136\u0137\5\u0105\u0083\2\u0137\u0143\3"+
"\2\2\2\u0138\u0139\7}\2\2\u0139\u013a\5\u0105\u0083\2\u013a\u013c\5\u0105"+
"\u0083\2\u013b\u013d\5\u0105\u0083\2\u013c\u013b\3\2\2\2\u013d\u013e\3"+
"\2\2\2\u013e\u013c\3\2\2\2\u013e\u013f\3\2\2\2\u013f\u0140\3\2\2\2\u0140"+
"\u0141\7\177\2\2\u0141\u0143\3\2\2\2\u0142\u0135\3\2\2\2\u0142\u0138\3"+
"\2\2\2\u0143\30\3\2\2\2\u0144\u0145\7\60\2\2\u0145\32\3\2\2\2\u0146\u0147"+
"\7^\2\2\u0147\u0148\7E\2\2\u0148\34\3\2\2\2\u0149\u014a\7^\2\2\u014a\u014b"+
"\7f\2\2\u014b\36\3\2\2\2\u014c\u014d\7^\2\2\u014d\u014e\7F\2\2\u014e "+
"\3\2\2\2\u014f\u0150\7^\2\2\u0150\u0151\7j\2\2\u0151\"\3\2\2\2\u0152\u0153"+
"\7^\2\2\u0153\u0154\7J\2\2\u0154$\3\2\2\2\u0155\u0156\7^\2\2\u0156\u0157"+
"\7P\2\2\u0157&\3\2\2\2\u0158\u0159\7^\2\2\u0159\u015a\7r\2\2\u015a\u015b"+
"\7}\2\2\u015b\u015c\3\2\2\2\u015c\u015d\5\u00fd\177\2\u015d\u015e\7\177"+
"\2\2\u015e(\3\2\2\2\u015f\u0160\7^\2\2\u0160\u0161\7R\2\2\u0161\u0162"+
"\7}\2\2\u0162\u0163\3\2\2\2\u0163\u0164\5\u00fd\177\2\u0164\u0165\7\177"+
"\2\2\u0165*\3\2\2\2\u0166\u0167\7^\2\2\u0167\u0168\7T\2\2\u0168,\3\2\2"+
"\2\u0169\u016a\7^\2\2\u016a\u016b\7u\2\2\u016b.\3\2\2\2\u016c\u016d\7"+
"^\2\2\u016d\u016e\7U\2\2\u016e\60\3\2\2\2\u016f\u0170\7^\2\2\u0170\u0171"+
"\7x\2\2\u0171\62\3\2\2\2\u0172\u0173\7^\2\2\u0173\u0174\7X\2\2\u0174\64"+
"\3\2\2\2\u0175\u0176\7^\2\2\u0176\u0177\7y\2\2\u0177\66\3\2\2\2\u0178"+
"\u0179\7^\2\2\u0179\u017a\7Y\2\2\u017a8\3\2\2\2\u017b\u017c\7^\2\2\u017c"+
"\u017d\7Z\2\2\u017d:\3\2\2\2\u017e\u017f\7]\2\2\u017f<\3\2\2\2\u0180\u0181"+
"\7_\2\2\u0181>\3\2\2\2\u0182\u0183\7`\2\2\u0183@\3\2\2\2\u0184\u0185\7"+
"/\2\2\u0185B\3\2\2\2\u0186\u0187\7]\2\2\u0187\u0188\7]\2\2\u0188\u0189"+
"\7<\2\2\u0189\u018a\3\2\2\2\u018a\u018b\5\u00ff\u0080\2\u018b\u018c\7"+
"<\2\2\u018c\u018d\7_\2\2\u018d\u018e\7_\2\2\u018eD\3\2\2\2\u018f\u0190"+
"\7]\2\2\u0190\u0191\7]\2\2\u0191\u0192\7<\2\2\u0192\u0193\7`\2\2\u0193"+
"\u0194\3\2\2\2\u0194\u0195\5\u00ff\u0080\2\u0195\u0196\7<\2\2\u0196\u0197"+
"\7_\2\2\u0197\u0198\7_\2\2\u0198F\3\2\2\2\u0199\u019a\7A\2\2\u019aH\3"+
"\2\2\2\u019b\u019c\7-\2\2\u019cJ\3\2\2\2\u019d\u019e\7,\2\2\u019eL\3\2"+
"\2\2\u019f\u01a0\7}\2\2\u01a0N\3\2\2\2\u01a1\u01a2\7\177\2\2\u01a2P\3"+
"\2\2\2\u01a3\u01a4\7.\2\2\u01a4R\3\2\2\2\u01a5\u01a6\7^\2\2\u01a6\u01a7"+
"\7d\2\2\u01a7T\3\2\2\2\u01a8\u01a9\7^\2\2\u01a9\u01aa\7D\2\2\u01aaV\3"+
"\2\2\2\u01ab\u01ac\7^\2\2\u01ac\u01ad\7C\2\2\u01adX\3\2\2\2\u01ae\u01af"+
"\7&\2\2\u01afZ\3\2\2\2\u01b0\u01b1\7^\2\2\u01b1\u01b2\7\\\2\2\u01b2\\"+
"\3\2\2\2\u01b3\u01b4\7^\2\2\u01b4\u01b5\7|\2\2\u01b5^\3\2\2\2\u01b6\u01b7"+
"\7^\2\2\u01b7\u01b8\7I\2\2\u01b8`\3\2\2\2\u01b9\u01ba\7^\2\2\u01ba\u01bb"+
"\7M\2\2\u01bbb\3\2\2\2\u01bc\u01bd\7^\2\2\u01bd\u01be\7i\2\2\u01bed\3"+
"\2\2\2\u01bf\u01c0\7^\2\2\u01c0\u01c1\7m\2\2\u01c1f\3\2\2\2\u01c2\u01c3"+
"\7~\2\2\u01c3h\3\2\2\2\u01c4\u01c5\7*\2\2\u01c5j\3\2\2\2\u01c6\u01c7\7"+
"+\2\2\u01c7l\3\2\2\2\u01c8\u01c9\7>\2\2\u01c9n\3\2\2\2\u01ca\u01cb\7@"+
"\2\2\u01cbp\3\2\2\2\u01cc\u01cd\7)\2\2\u01cdr\3\2\2\2\u01ce\u01cf\7a\2"+
"\2\u01cft\3\2\2\2\u01d0\u01d1\7<\2\2\u01d1v\3\2\2\2\u01d2\u01d3\7%\2\2"+
"\u01d3x\3\2\2\2\u01d4\u01d5\7?\2\2\u01d5z\3\2\2\2\u01d6\u01d7\7#\2\2\u01d7"+
"|\3\2\2\2\u01d8\u01d9\7(\2\2\u01d9~\3\2\2\2\u01da\u01db\7c\2\2\u01db\u0080"+
"\3\2\2\2\u01dc\u01dd\7d\2\2\u01dd\u0082\3\2\2\2\u01de\u01df\7e\2\2\u01df"+
"\u0084\3\2\2\2\u01e0\u01e1\7f\2\2\u01e1\u0086\3\2\2\2\u01e2\u01e3\7g\2"+
"\2\u01e3\u0088\3\2\2\2\u01e4\u01e5\7h\2\2\u01e5\u008a\3\2\2\2\u01e6\u01e7"+
"\7i\2\2\u01e7\u008c\3\2\2\2\u01e8\u01e9\7j\2\2\u01e9\u008e\3\2\2\2\u01ea"+
"\u01eb\7k\2\2\u01eb\u0090\3\2\2\2\u01ec\u01ed\7l\2\2\u01ed\u0092\3\2\2"+
"\2\u01ee\u01ef\7m\2\2\u01ef\u0094\3\2\2\2\u01f0\u01f1\7n\2\2\u01f1\u0096"+
"\3\2\2\2\u01f2\u01f3\7o\2\2\u01f3\u0098\3\2\2\2\u01f4\u01f5\7p\2\2\u01f5"+
"\u009a\3\2\2\2\u01f6\u01f7\7q\2\2\u01f7\u009c\3\2\2\2\u01f8\u01f9\7r\2"+
"\2\u01f9\u009e\3\2\2\2\u01fa\u01fb\7s\2\2\u01fb\u00a0\3\2\2\2\u01fc\u01fd"+
"\7t\2\2\u01fd\u00a2\3\2\2\2\u01fe\u01ff\7u\2\2\u01ff\u00a4\3\2\2\2\u0200"+
"\u0201\7v\2\2\u0201\u00a6\3\2\2\2\u0202\u0203\7w\2\2\u0203\u00a8\3\2\2"+
"\2\u0204\u0205\7x\2\2\u0205\u00aa\3\2\2\2\u0206\u0207\7y\2\2\u0207\u00ac"+
"\3\2\2\2\u0208\u0209\7z\2\2\u0209\u00ae\3\2\2\2\u020a\u020b\7{\2\2\u020b"+
"\u00b0\3\2\2\2\u020c\u020d\7|\2\2\u020d\u00b2\3\2\2\2\u020e\u020f\7C\2"+
"\2\u020f\u00b4\3\2\2\2\u0210\u0211\7D\2\2\u0211\u00b6\3\2\2\2\u0212\u0213"+
"\7E\2\2\u0213\u00b8\3\2\2\2\u0214\u0215\7F\2\2\u0215\u00ba\3\2\2\2\u0216"+
"\u0217\7G\2\2\u0217\u00bc\3\2\2\2\u0218\u0219\7H\2\2\u0219\u00be\3\2\2"+
"\2\u021a\u021b\7I\2\2\u021b\u00c0\3\2\2\2\u021c\u021d\7J\2\2\u021d\u00c2"+
"\3\2\2\2\u021e\u021f\7K\2\2\u021f\u00c4\3\2\2\2\u0220\u0221\7L\2\2\u0221"+
"\u00c6\3\2\2\2\u0222\u0223\7M\2\2\u0223\u00c8\3\2\2\2\u0224\u0225\7N\2"+
"\2\u0225\u00ca\3\2\2\2\u0226\u0227\7O\2\2\u0227\u00cc\3\2\2\2\u0228\u0229"+
"\7P\2\2\u0229\u00ce\3\2\2\2\u022a\u022b\7Q\2\2\u022b\u00d0\3\2\2\2\u022c"+
"\u022d\7R\2\2\u022d\u00d2\3\2\2\2\u022e\u022f\7S\2\2\u022f\u00d4\3\2\2"+
"\2\u0230\u0231\7T\2\2\u0231\u00d6\3\2\2\2\u0232\u0233\7U\2\2\u0233\u00d8"+
"\3\2\2\2\u0234\u0235\7V\2\2\u0235\u00da\3\2\2\2\u0236\u0237\7W\2\2\u0237"+
"\u00dc\3\2\2\2\u0238\u0239\7X\2\2\u0239\u00de\3\2\2\2\u023a\u023b\7Y\2"+
"\2\u023b\u00e0\3\2\2\2\u023c\u023d\7Z\2\2\u023d\u00e2\3\2\2\2\u023e\u023f"+
"\7[\2\2\u023f\u00e4\3\2\2\2\u0240\u0241\7\\\2\2\u0241\u00e6\3\2\2\2\u0242"+
"\u0243\7\63\2\2\u0243\u00e8\3\2\2\2\u0244\u0245\7\64\2\2\u0245\u00ea\3"+
"\2\2\2\u0246\u0247\7\65\2\2\u0247\u00ec\3\2\2\2\u0248\u0249\7\66\2\2\u0249"+
"\u00ee\3\2\2\2\u024a\u024b\7\67\2\2\u024b\u00f0\3\2\2\2\u024c\u024d\7"+
"8\2\2\u024d\u00f2\3\2\2\2\u024e\u024f\79\2\2\u024f\u00f4\3\2\2\2\u0250"+
"\u0251\7:\2\2\u0251\u00f6\3\2\2\2\u0252\u0253\7;\2\2\u0253\u00f8\3\2\2"+
"\2\u0254\u0255\7\62\2\2\u0255\u00fa\3\2\2\2\u0256\u0257\13\2\2\2\u0257"+
"\u00fc\3\2\2\2\u0258\u025b\7a\2\2\u0259\u025b\5\u0101\u0081\2\u025a\u0258"+
"\3\2\2\2\u025a\u0259\3\2\2\2\u025b\u025c\3\2\2\2\u025c\u025a\3\2\2\2\u025c"+
"\u025d\3\2\2\2\u025d\u00fe\3\2\2\2\u025e\u0260\5\u0101\u0081\2\u025f\u025e"+
"\3\2\2\2\u0260\u0261\3\2\2\2\u0261\u025f\3\2\2\2\u0261\u0262\3\2\2\2\u0262"+
"\u0100\3\2\2\2\u0263\u0264\t\2\2\2\u0264\u0102\3\2\2\2\u0265\u0266\n\2"+
"\2\2\u0266\u0104\3\2\2\2\u0267\u0268\t\3\2\2\u0268\u0106\3\2\2\2\u0269"+
"\u026a\t\4\2\2\u026a\u0108\3\2\2\2\n\2\u0112\u011f\u013e\u0142\u025a\u025c"+
"\u0261\2";
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,379 @@
package ru.touchin.roboswag.textprocessing.pcre.parser;
import org.antlr.v4.runtime.tree.ParseTreeListener;
/**
* This interface defines a complete listener for a parse tree produced by
* {@link PCREParser}.
*/
public interface PCREListener extends ParseTreeListener {
/**
* Enter a parse tree produced by {@link PCREParser#parse}.
* @param ctx the parse tree
*/
void enterParse(PCREParser.ParseContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#parse}.
* @param ctx the parse tree
*/
void exitParse(PCREParser.ParseContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#alternation}.
* @param ctx the parse tree
*/
void enterAlternation(PCREParser.AlternationContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#alternation}.
* @param ctx the parse tree
*/
void exitAlternation(PCREParser.AlternationContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#expr}.
* @param ctx the parse tree
*/
void enterExpr(PCREParser.ExprContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#expr}.
* @param ctx the parse tree
*/
void exitExpr(PCREParser.ExprContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#element}.
* @param ctx the parse tree
*/
void enterElement(PCREParser.ElementContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#element}.
* @param ctx the parse tree
*/
void exitElement(PCREParser.ElementContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#quantifier}.
* @param ctx the parse tree
*/
void enterQuantifier(PCREParser.QuantifierContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#quantifier}.
* @param ctx the parse tree
*/
void exitQuantifier(PCREParser.QuantifierContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#quantifier_type}.
* @param ctx the parse tree
*/
void enterQuantifier_type(PCREParser.Quantifier_typeContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#quantifier_type}.
* @param ctx the parse tree
*/
void exitQuantifier_type(PCREParser.Quantifier_typeContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#character_class}.
* @param ctx the parse tree
*/
void enterCharacter_class(PCREParser.Character_classContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#character_class}.
* @param ctx the parse tree
*/
void exitCharacter_class(PCREParser.Character_classContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#backreference}.
* @param ctx the parse tree
*/
void enterBackreference(PCREParser.BackreferenceContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#backreference}.
* @param ctx the parse tree
*/
void exitBackreference(PCREParser.BackreferenceContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#backreference_or_octal}.
* @param ctx the parse tree
*/
void enterBackreference_or_octal(PCREParser.Backreference_or_octalContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#backreference_or_octal}.
* @param ctx the parse tree
*/
void exitBackreference_or_octal(PCREParser.Backreference_or_octalContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#capture}.
* @param ctx the parse tree
*/
void enterCapture(PCREParser.CaptureContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#capture}.
* @param ctx the parse tree
*/
void exitCapture(PCREParser.CaptureContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#non_capture}.
* @param ctx the parse tree
*/
void enterNon_capture(PCREParser.Non_captureContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#non_capture}.
* @param ctx the parse tree
*/
void exitNon_capture(PCREParser.Non_captureContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#comment}.
* @param ctx the parse tree
*/
void enterComment(PCREParser.CommentContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#comment}.
* @param ctx the parse tree
*/
void exitComment(PCREParser.CommentContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#option}.
* @param ctx the parse tree
*/
void enterOption(PCREParser.OptionContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#option}.
* @param ctx the parse tree
*/
void exitOption(PCREParser.OptionContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#option_flags}.
* @param ctx the parse tree
*/
void enterOption_flags(PCREParser.Option_flagsContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#option_flags}.
* @param ctx the parse tree
*/
void exitOption_flags(PCREParser.Option_flagsContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#option_flag}.
* @param ctx the parse tree
*/
void enterOption_flag(PCREParser.Option_flagContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#option_flag}.
* @param ctx the parse tree
*/
void exitOption_flag(PCREParser.Option_flagContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#look_around}.
* @param ctx the parse tree
*/
void enterLook_around(PCREParser.Look_aroundContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#look_around}.
* @param ctx the parse tree
*/
void exitLook_around(PCREParser.Look_aroundContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#subroutine_reference}.
* @param ctx the parse tree
*/
void enterSubroutine_reference(PCREParser.Subroutine_referenceContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#subroutine_reference}.
* @param ctx the parse tree
*/
void exitSubroutine_reference(PCREParser.Subroutine_referenceContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#conditional}.
* @param ctx the parse tree
*/
void enterConditional(PCREParser.ConditionalContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#conditional}.
* @param ctx the parse tree
*/
void exitConditional(PCREParser.ConditionalContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#backtrack_control}.
* @param ctx the parse tree
*/
void enterBacktrack_control(PCREParser.Backtrack_controlContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#backtrack_control}.
* @param ctx the parse tree
*/
void exitBacktrack_control(PCREParser.Backtrack_controlContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#newline_convention}.
* @param ctx the parse tree
*/
void enterNewline_convention(PCREParser.Newline_conventionContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#newline_convention}.
* @param ctx the parse tree
*/
void exitNewline_convention(PCREParser.Newline_conventionContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#callout}.
* @param ctx the parse tree
*/
void enterCallout(PCREParser.CalloutContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#callout}.
* @param ctx the parse tree
*/
void exitCallout(PCREParser.CalloutContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#atom}.
* @param ctx the parse tree
*/
void enterAtom(PCREParser.AtomContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#atom}.
* @param ctx the parse tree
*/
void exitAtom(PCREParser.AtomContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#cc_atom}.
* @param ctx the parse tree
*/
void enterCc_atom(PCREParser.Cc_atomContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#cc_atom}.
* @param ctx the parse tree
*/
void exitCc_atom(PCREParser.Cc_atomContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#shared_atom}.
* @param ctx the parse tree
*/
void enterShared_atom(PCREParser.Shared_atomContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#shared_atom}.
* @param ctx the parse tree
*/
void exitShared_atom(PCREParser.Shared_atomContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#literal}.
* @param ctx the parse tree
*/
void enterLiteral(PCREParser.LiteralContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#literal}.
* @param ctx the parse tree
*/
void exitLiteral(PCREParser.LiteralContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#cc_literal}.
* @param ctx the parse tree
*/
void enterCc_literal(PCREParser.Cc_literalContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#cc_literal}.
* @param ctx the parse tree
*/
void exitCc_literal(PCREParser.Cc_literalContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#shared_literal}.
* @param ctx the parse tree
*/
void enterShared_literal(PCREParser.Shared_literalContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#shared_literal}.
* @param ctx the parse tree
*/
void exitShared_literal(PCREParser.Shared_literalContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#number}.
* @param ctx the parse tree
*/
void enterNumber(PCREParser.NumberContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#number}.
* @param ctx the parse tree
*/
void exitNumber(PCREParser.NumberContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#octal_char}.
* @param ctx the parse tree
*/
void enterOctal_char(PCREParser.Octal_charContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#octal_char}.
* @param ctx the parse tree
*/
void exitOctal_char(PCREParser.Octal_charContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#octal_digit}.
* @param ctx the parse tree
*/
void enterOctal_digit(PCREParser.Octal_digitContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#octal_digit}.
* @param ctx the parse tree
*/
void exitOctal_digit(PCREParser.Octal_digitContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#digits}.
* @param ctx the parse tree
*/
void enterDigits(PCREParser.DigitsContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#digits}.
* @param ctx the parse tree
*/
void exitDigits(PCREParser.DigitsContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#digit}.
* @param ctx the parse tree
*/
void enterDigit(PCREParser.DigitContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#digit}.
* @param ctx the parse tree
*/
void exitDigit(PCREParser.DigitContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#name}.
* @param ctx the parse tree
*/
void enterName(PCREParser.NameContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#name}.
* @param ctx the parse tree
*/
void exitName(PCREParser.NameContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#alpha_nums}.
* @param ctx the parse tree
*/
void enterAlpha_nums(PCREParser.Alpha_numsContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#alpha_nums}.
* @param ctx the parse tree
*/
void exitAlpha_nums(PCREParser.Alpha_numsContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#non_close_parens}.
* @param ctx the parse tree
*/
void enterNon_close_parens(PCREParser.Non_close_parensContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#non_close_parens}.
* @param ctx the parse tree
*/
void exitNon_close_parens(PCREParser.Non_close_parensContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#non_close_paren}.
* @param ctx the parse tree
*/
void enterNon_close_paren(PCREParser.Non_close_parenContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#non_close_paren}.
* @param ctx the parse tree
*/
void exitNon_close_paren(PCREParser.Non_close_parenContext ctx);
/**
* Enter a parse tree produced by {@link PCREParser#letter}.
* @param ctx the parse tree
*/
void enterLetter(PCREParser.LetterContext ctx);
/**
* Exit a parse tree produced by {@link PCREParser#letter}.
* @param ctx the parse tree
*/
void exitLetter(PCREParser.LetterContext ctx);
}

View File

@ -0,0 +1,234 @@
package ru.touchin.roboswag.textprocessing.pcre.parser;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
/**
* This interface defines a complete generic visitor for a parse tree produced
* by {@link PCREParser}.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public interface PCREVisitor<T> extends ParseTreeVisitor<T> {
/**
* Visit a parse tree produced by {@link PCREParser#parse}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitParse(PCREParser.ParseContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#alternation}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitAlternation(PCREParser.AlternationContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExpr(PCREParser.ExprContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#element}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitElement(PCREParser.ElementContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#quantifier}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitQuantifier(PCREParser.QuantifierContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#quantifier_type}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitQuantifier_type(PCREParser.Quantifier_typeContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#character_class}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitCharacter_class(PCREParser.Character_classContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#backreference}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitBackreference(PCREParser.BackreferenceContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#backreference_or_octal}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitBackreference_or_octal(PCREParser.Backreference_or_octalContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#capture}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitCapture(PCREParser.CaptureContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#non_capture}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNon_capture(PCREParser.Non_captureContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#comment}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitComment(PCREParser.CommentContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#option}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitOption(PCREParser.OptionContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#option_flags}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitOption_flags(PCREParser.Option_flagsContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#option_flag}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitOption_flag(PCREParser.Option_flagContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#look_around}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitLook_around(PCREParser.Look_aroundContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#subroutine_reference}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitSubroutine_reference(PCREParser.Subroutine_referenceContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#conditional}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitConditional(PCREParser.ConditionalContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#backtrack_control}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitBacktrack_control(PCREParser.Backtrack_controlContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#newline_convention}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNewline_convention(PCREParser.Newline_conventionContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#callout}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitCallout(PCREParser.CalloutContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#atom}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitAtom(PCREParser.AtomContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#cc_atom}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitCc_atom(PCREParser.Cc_atomContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#shared_atom}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitShared_atom(PCREParser.Shared_atomContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#literal}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitLiteral(PCREParser.LiteralContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#cc_literal}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitCc_literal(PCREParser.Cc_literalContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#shared_literal}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitShared_literal(PCREParser.Shared_literalContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#number}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNumber(PCREParser.NumberContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#octal_char}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitOctal_char(PCREParser.Octal_charContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#octal_digit}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitOctal_digit(PCREParser.Octal_digitContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#digits}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitDigits(PCREParser.DigitsContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#digit}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitDigit(PCREParser.DigitContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#name}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitName(PCREParser.NameContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#alpha_nums}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitAlpha_nums(PCREParser.Alpha_numsContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#non_close_parens}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNon_close_parens(PCREParser.Non_close_parensContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#non_close_paren}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNon_close_paren(PCREParser.Non_close_parenContext ctx);
/**
* Visit a parse tree produced by {@link PCREParser#letter}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitLetter(PCREParser.LetterContext ctx);
}

View File

@ -0,0 +1,16 @@
package ru.touchin.roboswag.textprocessing.validators
import ru.tinkoff.decoro.slots.Slot
class CustomValidator private constructor(
private val slotSymbols: List<Char>
) : Slot.SlotValidator {
companion object {
fun customSlot(slotSymbols: List<Char>) = Slot(null, CustomValidator(slotSymbols))
}
override fun validate(value: Char): Boolean {
return slotSymbols.contains(value)
}
}

View File

@ -0,0 +1,57 @@
package ru.touchin.roboswag.textprocessing
import org.junit.Assert
import org.junit.Test
class TextFormatterTest {
@Test
fun test_bank_card_expire_formatting() {
val regex = "(\\d{2})\\/?(\\d{2})"
val inputText = "0622"
val item = TextFormatter(regex)
Assert.assertEquals("$1\\/$2", item.getRegexReplace())
Assert.assertEquals("06/22", item.getFormattedText(inputText))
Assert.assertEquals("12/34", item.getPlaceholder())
}
@Test
fun test_number_bank_card_formatting() {
val regex = "(\\d{4}) ?(\\d{4}) ?(\\d{4}) ?(\\d{4})"
val inputText = "1234345612353534"
val item = TextFormatter(regex)
Assert.assertEquals("\$1 \$2 \$3 \$4", item.getRegexReplace())
Assert.assertEquals("1234 3456 1235 3534", item.getFormattedText(inputText))
Assert.assertEquals("1234 5678 9012 3456", item.getPlaceholder())
}
@Test
fun test_phone_number_formatting() {
val regex = "(?:\\+7 )?\\(?(\\d{3})\\)? ?(\\d{3}) ?(\\d{2}) ?(\\d{2})"
val inputText = "9091344422"
val item = TextFormatter(regex)
Assert.assertEquals("\\+7 \\($1\\) $2 $3 $4", item.getRegexReplace())
Assert.assertEquals("+7 (909) 134 44 22", item.getFormattedText(inputText))
Assert.assertEquals("+7 (123) 456 78 90", item.getPlaceholder())
}
@Test
fun test_birthday_certificate_number_formatting() {
val regex = "([A-Z]{2})-?([А-Я]{2}) ?№? ?(\\d{6})"
val inputText = "IVБЮ349823"
val item = TextFormatter(regex)
Assert.assertEquals("\$1-\$2 № \$3", item.getRegexReplace())
Assert.assertEquals("IV-БЮ № 349823", item.getFormattedText(inputText))
Assert.assertEquals("AB-АБ № 123456", item.getPlaceholder())
}
@Test
fun test_rub_sum_formatting() {
val regex = "(\\d+)([.,]\\d+)? ?₽?"
val inputText = "5332.4"
val item = TextFormatter(regex)
Assert.assertEquals("\$1\$2 ₽", item.getRegexReplace())
Assert.assertEquals("5332.4 ₽", item.getFormattedText(inputText))
Assert.assertEquals("1.2 ₽", item.getPlaceholder())
}
}