From b5326f3cfea07f745c7de92f0dc42529783abe81 Mon Sep 17 00:00:00 2001 From: Austin Blake Date: Thu, 6 Jun 2024 09:23:12 -0500 Subject: [PATCH] Adding an escape sequence for brackets, updating decompile to utilize it, and adding a test for it --- .../Compiler/MessageScriptCompiler.cs | 13 +- .../Compiler/Parser/MessageScriptLexer.cs | 125 +++++++++--------- .../Compiler/Parser/MessageScriptLexer.g4 | 4 +- .../Compiler/Parser/MessageScriptLexer.tokens | 1 - .../Decompiler/MessageScriptDecompiler.cs | 7 +- .../MessageScriptTests.cs | 27 ++++ .../TestResources/EscapeChar.bmd | Bin 0 -> 28215 bytes 7 files changed, 107 insertions(+), 70 deletions(-) create mode 100644 Source/AtlusScriptLibraryTests/TestResources/EscapeChar.bmd diff --git a/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/MessageScriptCompiler.cs b/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/MessageScriptCompiler.cs index b035b842..e1113443 100644 --- a/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/MessageScriptCompiler.cs +++ b/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/MessageScriptCompiler.cs @@ -22,6 +22,11 @@ namespace AtlusScriptLibrary.MessageScriptLanguage.Compiler; /// public class MessageScriptCompiler { + public static readonly Dictionary ESCAPE_SEQUENCES = new Dictionary(){ + { "\\[", "[" }, + { "\\]", "]" } + }; + private readonly Logger mLogger; private readonly FormatVersion mVersion; private readonly HashSet mImportedFileHashSet; @@ -659,7 +664,13 @@ private bool TryCompileTokenText(MessageScriptParser.TokenTextContext context, o if (textWithoutNewlines.Length == 0) continue; // filter out standalone newlines - lineToken = new StringToken(textWithoutNewlines); + var textWithoutEscapeChars = textWithoutNewlines; + foreach(var sequence in ESCAPE_SEQUENCES) + { + textWithoutEscapeChars = textWithoutEscapeChars.Replace(sequence.Key, sequence.Value); + } + + lineToken = new StringToken(textWithoutEscapeChars); } else { diff --git a/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.cs b/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.cs index 1a030fb5..4c72206a 100644 --- a/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.cs +++ b/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.cs @@ -1,14 +1,14 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// ANTLR Version: 4.6.4 +// ANTLR Version: 4.6.6 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ -// Generated from ..\..\..\AtlusScriptLibrary\MessageScriptLanguage\Compiler\Parser\MessageScriptLexer.g4 by ANTLR 4.6.4 +// Generated from Compiler/Parser/MessageScriptLexer.g4 by ANTLR 4.6.6 // Unreachable code detected #pragma warning disable 0162 @@ -25,13 +25,13 @@ namespace AtlusScriptLibrary.FlowScriptLanguage.Compiler.Parser { using Antlr4.Runtime.Misc; using DFA = Antlr4.Runtime.Dfa.DFA; -[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.6.4")] +[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.6.6")] [System.CLSCompliant(false)] public partial class MessageScriptLexer : Lexer { public const int OpenCode=1, CloseText=2, Text=3, MessageDialogTagId=4, SelectionDialogTagId=5, SelectionDialogPatternId=6, CloseCode=7, OpenText=8, IntLiteral=9, Identifier=10, - Whitespace=11, BlockComment=12; + Whitespace=11; public const int MessageScriptCode = 1; public static string[] modeNames = { "DEFAULT_MODE", "MessageScriptCode" @@ -41,7 +41,7 @@ public const int "OpenCode", "CloseText", "Text", "MessageDialogTagId", "SelectionDialogTagId", "SelectionDialogPatternId", "CloseCode", "OpenText", "IdentifierEscape", "IntLiteral", "Identifier", "DecIntLiteral", "HexIntLiteral", "Letter", - "Digit", "HexDigit", "HexLiteralPrefix", "Sign", "Whitespace", "BlockComment" + "Digit", "HexDigit", "HexLiteralPrefix", "Sign", "Whitespace" }; @@ -57,7 +57,7 @@ public MessageScriptLexer(ICharStream input) private static readonly string[] _SymbolicNames = { null, "OpenCode", "CloseText", "Text", "MessageDialogTagId", "SelectionDialogTagId", "SelectionDialogPatternId", "CloseCode", "OpenText", "IntLiteral", "Identifier", - "Whitespace", "BlockComment" + "Whitespace" }; public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); @@ -107,67 +107,62 @@ public override IVocabulary Vocabulary public override string SerializedAtn { get { return _serializedATN; } } public static readonly string _serializedATN = - "\x3\xAF6F\x8320\x479D\xB75C\x4880\x1605\x191C\xAB37\x2\xE\xA6\b\x1\b\x1"+ + "\x3\xAF6F\x8320\x479D\xB75C\x4880\x1605\x191C\xAB37\x2\r\x9A\b\x1\b\x1"+ "\x4\x2\t\x2\x4\x3\t\x3\x4\x4\t\x4\x4\x5\t\x5\x4\x6\t\x6\x4\a\t\a\x4\b"+ "\t\b\x4\t\t\t\x4\n\t\n\x4\v\t\v\x4\f\t\f\x4\r\t\r\x4\xE\t\xE\x4\xF\t\xF"+ - "\x4\x10\t\x10\x4\x11\t\x11\x4\x12\t\x12\x4\x13\t\x13\x4\x14\t\x14\x4\x15"+ - "\t\x15\x3\x2\x3\x2\x3\x2\x3\x2\x3\x3\x3\x3\x3\x3\x3\x3\x3\x4\x6\x4\x36"+ - "\n\x4\r\x4\xE\x4\x37\x3\x5\x3\x5\x3\x5\x3\x5\x3\x5\x3\x5\x5\x5@\n\x5\x3"+ - "\x6\x3\x6\x3\x6\x3\x6\x3\a\x3\a\x3\a\x3\a\x3\a\x3\a\x3\a\x3\a\x3\a\x5"+ - "\aO\n\a\x3\b\x3\b\x3\b\x3\b\x3\t\x3\t\x3\t\x3\t\x3\n\x3\n\x3\n\x3\v\x3"+ - "\v\x5\v^\n\v\x3\f\x3\f\x5\f\x62\n\f\x3\f\x3\f\x3\f\a\fg\n\f\f\f\xE\fj"+ - "\v\f\x3\f\x3\f\a\fn\n\f\f\f\xE\fq\v\f\x3\f\x3\f\x5\fu\n\f\x3\r\x5\rx\n"+ - "\r\x3\r\x6\r{\n\r\r\r\xE\r|\x3\xE\x5\xE\x80\n\xE\x3\xE\x3\xE\x6\xE\x84"+ - "\n\xE\r\xE\xE\xE\x85\x3\xF\x3\xF\x3\x10\x3\x10\x3\x11\x3\x11\x5\x11\x8E"+ - "\n\x11\x3\x12\x3\x12\x3\x12\x3\x13\x3\x13\x3\x14\x3\x14\x3\x14\x3\x14"+ - "\x3\x15\x3\x15\x3\x15\x3\x15\a\x15\x9D\n\x15\f\x15\xE\x15\xA0\v\x15\x3"+ - "\x15\x3\x15\x3\x15\x3\x15\x3\x15\x3\x9E\x2\x2\x16\x4\x2\x3\x6\x2\x4\b"+ - "\x2\x5\n\x2\x6\f\x2\a\xE\x2\b\x10\x2\t\x12\x2\n\x14\x2\x2\x16\x2\v\x18"+ - "\x2\f\x1A\x2\x2\x1C\x2\x2\x1E\x2\x2 \x2\x2\"\x2\x2$\x2\x2&\x2\x2(\x2\r"+ - "*\x2\xE\x4\x2\x3\n\x4\x2]]__\x3\x2\x62\x62\x4\x2\x43\\\x63|\x3\x2\x32"+ - ";\x4\x2\x43H\x63h\x4\x2ZZzz\x4\x2--//\x5\x2\v\f\xF\xF\"\"\xAC\x2\x4\x3"+ - "\x2\x2\x2\x2\x6\x3\x2\x2\x2\x2\b\x3\x2\x2\x2\x3\n\x3\x2\x2\x2\x3\f\x3"+ - "\x2\x2\x2\x3\xE\x3\x2\x2\x2\x3\x10\x3\x2\x2\x2\x3\x12\x3\x2\x2\x2\x3\x16"+ - "\x3\x2\x2\x2\x3\x18\x3\x2\x2\x2\x3(\x3\x2\x2\x2\x3*\x3\x2\x2\x2\x4,\x3"+ - "\x2\x2\x2\x6\x30\x3\x2\x2\x2\b\x35\x3\x2\x2\x2\n?\x3\x2\x2\x2\f\x41\x3"+ - "\x2\x2\x2\xEN\x3\x2\x2\x2\x10P\x3\x2\x2\x2\x12T\x3\x2\x2\x2\x14X\x3\x2"+ - "\x2\x2\x16]\x3\x2\x2\x2\x18t\x3\x2\x2\x2\x1Aw\x3\x2\x2\x2\x1C\x7F\x3\x2"+ - "\x2\x2\x1E\x87\x3\x2\x2\x2 \x89\x3\x2\x2\x2\"\x8D\x3\x2\x2\x2$\x8F\x3"+ - "\x2\x2\x2&\x92\x3\x2\x2\x2(\x94\x3\x2\x2\x2*\x98\x3\x2\x2\x2,-\a]\x2\x2"+ - "-.\x3\x2\x2\x2./\b\x2\x2\x2/\x5\x3\x2\x2\x2\x30\x31\a_\x2\x2\x31\x32\x3"+ - "\x2\x2\x2\x32\x33\b\x3\x2\x2\x33\a\x3\x2\x2\x2\x34\x36\n\x2\x2\x2\x35"+ - "\x34\x3\x2\x2\x2\x36\x37\x3\x2\x2\x2\x37\x35\x3\x2\x2\x2\x37\x38\x3\x2"+ - "\x2\x2\x38\t\x3\x2\x2\x2\x39:\ao\x2\x2:;\au\x2\x2;@\ai\x2\x2<=\a\x66\x2"+ - "\x2=>\an\x2\x2>@\ai\x2\x2?\x39\x3\x2\x2\x2?<\x3\x2\x2\x2@\v\x3\x2\x2\x2"+ - "\x41\x42\au\x2\x2\x42\x43\ag\x2\x2\x43\x44\an\x2\x2\x44\r\x3\x2\x2\x2"+ - "\x45\x46\av\x2\x2\x46G\aq\x2\x2GO\ar\x2\x2HI\a\x64\x2\x2IJ\aq\x2\x2JK"+ - "\av\x2\x2KL\av\x2\x2LM\aq\x2\x2MO\ao\x2\x2N\x45\x3\x2\x2\x2NH\x3\x2\x2"+ - "\x2O\xF\x3\x2\x2\x2PQ\a_\x2\x2QR\x3\x2\x2\x2RS\b\b\x3\x2S\x11\x3\x2\x2"+ - "\x2TU\a]\x2\x2UV\x3\x2\x2\x2VW\b\t\x3\x2W\x13\x3\x2\x2\x2XY\a\x62\x2\x2"+ - "YZ\a\x62\x2\x2Z\x15\x3\x2\x2\x2[^\x5\x1A\r\x2\\^\x5\x1C\xE\x2][\x3\x2"+ - "\x2\x2]\\\x3\x2\x2\x2^\x17\x3\x2\x2\x2_\x62\x5\x1E\xF\x2`\x62\a\x61\x2"+ - "\x2\x61_\x3\x2\x2\x2\x61`\x3\x2\x2\x2\x62h\x3\x2\x2\x2\x63g\x5\x1E\xF"+ - "\x2\x64g\a\x61\x2\x2\x65g\x5 \x10\x2\x66\x63\x3\x2\x2\x2\x66\x64\x3\x2"+ - "\x2\x2\x66\x65\x3\x2\x2\x2gj\x3\x2\x2\x2h\x66\x3\x2\x2\x2hi\x3\x2\x2\x2"+ - "iu\x3\x2\x2\x2jh\x3\x2\x2\x2ko\x5\x14\n\x2ln\n\x3\x2\x2ml\x3\x2\x2\x2"+ - "nq\x3\x2\x2\x2om\x3\x2\x2\x2op\x3\x2\x2\x2pr\x3\x2\x2\x2qo\x3\x2\x2\x2"+ - "rs\x5\x14\n\x2su\x3\x2\x2\x2t\x61\x3\x2\x2\x2tk\x3\x2\x2\x2u\x19\x3\x2"+ - "\x2\x2vx\x5&\x13\x2wv\x3\x2\x2\x2wx\x3\x2\x2\x2xz\x3\x2\x2\x2y{\x5 \x10"+ - "\x2zy\x3\x2\x2\x2{|\x3\x2\x2\x2|z\x3\x2\x2\x2|}\x3\x2\x2\x2}\x1B\x3\x2"+ - "\x2\x2~\x80\x5&\x13\x2\x7F~\x3\x2\x2\x2\x7F\x80\x3\x2\x2\x2\x80\x81\x3"+ - "\x2\x2\x2\x81\x83\x5$\x12\x2\x82\x84\x5\"\x11\x2\x83\x82\x3\x2\x2\x2\x84"+ - "\x85\x3\x2\x2\x2\x85\x83\x3\x2\x2\x2\x85\x86\x3\x2\x2\x2\x86\x1D\x3\x2"+ - "\x2\x2\x87\x88\t\x4\x2\x2\x88\x1F\x3\x2\x2\x2\x89\x8A\t\x5\x2\x2\x8A!"+ - "\x3\x2\x2\x2\x8B\x8E\x5 \x10\x2\x8C\x8E\t\x6\x2\x2\x8D\x8B\x3\x2\x2\x2"+ - "\x8D\x8C\x3\x2\x2\x2\x8E#\x3\x2\x2\x2\x8F\x90\a\x32\x2\x2\x90\x91\t\a"+ - "\x2\x2\x91%\x3\x2\x2\x2\x92\x93\t\b\x2\x2\x93\'\x3\x2\x2\x2\x94\x95\t"+ - "\t\x2\x2\x95\x96\x3\x2\x2\x2\x96\x97\b\x14\x4\x2\x97)\x3\x2\x2\x2\x98"+ - "\x99\a\x31\x2\x2\x99\x9A\a,\x2\x2\x9A\x9E\x3\x2\x2\x2\x9B\x9D\v\x2\x2"+ - "\x2\x9C\x9B\x3\x2\x2\x2\x9D\xA0\x3\x2\x2\x2\x9E\x9F\x3\x2\x2\x2\x9E\x9C"+ - "\x3\x2\x2\x2\x9F\xA1\x3\x2\x2\x2\xA0\x9E\x3\x2\x2\x2\xA1\xA2\a,\x2\x2"+ - "\xA2\xA3\a\x31\x2\x2\xA3\xA4\x3\x2\x2\x2\xA4\xA5\b\x15\x4\x2\xA5+\x3\x2"+ - "\x2\x2\x13\x2\x3\x37?N]\x61\x66hotw|\x7F\x85\x8D\x9E\x5\a\x3\x2\x6\x2"+ - "\x2\b\x2\x2"; + "\x4\x10\t\x10\x4\x11\t\x11\x4\x12\t\x12\x4\x13\t\x13\x4\x14\t\x14\x3\x2"+ + "\x3\x2\x3\x2\x3\x2\x3\x3\x3\x3\x3\x3\x3\x3\x3\x4\x3\x4\x3\x4\x3\x4\x3"+ + "\x4\x6\x4\x38\n\x4\r\x4\xE\x4\x39\x3\x5\x3\x5\x3\x5\x3\x5\x3\x5\x3\x5"+ + "\x5\x5\x42\n\x5\x3\x6\x3\x6\x3\x6\x3\x6\x3\a\x3\a\x3\a\x3\a\x3\a\x3\a"+ + "\x3\a\x3\a\x3\a\x5\aQ\n\a\x3\b\x3\b\x3\b\x3\b\x3\t\x3\t\x3\t\x3\t\x3\n"+ + "\x3\n\x3\n\x3\v\x3\v\x5\v`\n\v\x3\f\x3\f\x5\f\x64\n\f\x3\f\x3\f\x3\f\a"+ + "\fi\n\f\f\f\xE\fl\v\f\x3\f\x3\f\a\fp\n\f\f\f\xE\fs\v\f\x3\f\x3\f\x5\f"+ + "w\n\f\x3\r\x5\rz\n\r\x3\r\x6\r}\n\r\r\r\xE\r~\x3\xE\x5\xE\x82\n\xE\x3"+ + "\xE\x3\xE\x6\xE\x86\n\xE\r\xE\xE\xE\x87\x3\xF\x3\xF\x3\x10\x3\x10\x3\x11"+ + "\x3\x11\x5\x11\x90\n\x11\x3\x12\x3\x12\x3\x12\x3\x13\x3\x13\x3\x14\x3"+ + "\x14\x3\x14\x3\x14\x2\x2\x2\x15\x4\x2\x3\x6\x2\x4\b\x2\x5\n\x2\x6\f\x2"+ + "\a\xE\x2\b\x10\x2\t\x12\x2\n\x14\x2\x2\x16\x2\v\x18\x2\f\x1A\x2\x2\x1C"+ + "\x2\x2\x1E\x2\x2 \x2\x2\"\x2\x2$\x2\x2&\x2\x2(\x2\r\x4\x2\x3\n\x4\x2]"+ + "]__\x3\x2\x62\x62\x4\x2\x43\\\x63|\x3\x2\x32;\x4\x2\x43H\x63h\x4\x2ZZ"+ + "zz\x4\x2--//\x5\x2\v\f\xF\xF\"\"\xA1\x2\x4\x3\x2\x2\x2\x2\x6\x3\x2\x2"+ + "\x2\x2\b\x3\x2\x2\x2\x3\n\x3\x2\x2\x2\x3\f\x3\x2\x2\x2\x3\xE\x3\x2\x2"+ + "\x2\x3\x10\x3\x2\x2\x2\x3\x12\x3\x2\x2\x2\x3\x16\x3\x2\x2\x2\x3\x18\x3"+ + "\x2\x2\x2\x3(\x3\x2\x2\x2\x4*\x3\x2\x2\x2\x6.\x3\x2\x2\x2\b\x37\x3\x2"+ + "\x2\x2\n\x41\x3\x2\x2\x2\f\x43\x3\x2\x2\x2\xEP\x3\x2\x2\x2\x10R\x3\x2"+ + "\x2\x2\x12V\x3\x2\x2\x2\x14Z\x3\x2\x2\x2\x16_\x3\x2\x2\x2\x18v\x3\x2\x2"+ + "\x2\x1Ay\x3\x2\x2\x2\x1C\x81\x3\x2\x2\x2\x1E\x89\x3\x2\x2\x2 \x8B\x3\x2"+ + "\x2\x2\"\x8F\x3\x2\x2\x2$\x91\x3\x2\x2\x2&\x94\x3\x2\x2\x2(\x96\x3\x2"+ + "\x2\x2*+\a]\x2\x2+,\x3\x2\x2\x2,-\b\x2\x2\x2-\x5\x3\x2\x2\x2./\a_\x2\x2"+ + "/\x30\x3\x2\x2\x2\x30\x31\b\x3\x2\x2\x31\a\x3\x2\x2\x2\x32\x33\a^\x2\x2"+ + "\x33\x38\a]\x2\x2\x34\x35\a^\x2\x2\x35\x38\a_\x2\x2\x36\x38\n\x2\x2\x2"+ + "\x37\x32\x3\x2\x2\x2\x37\x34\x3\x2\x2\x2\x37\x36\x3\x2\x2\x2\x38\x39\x3"+ + "\x2\x2\x2\x39\x37\x3\x2\x2\x2\x39:\x3\x2\x2\x2:\t\x3\x2\x2\x2;<\ao\x2"+ + "\x2<=\au\x2\x2=\x42\ai\x2\x2>?\a\x66\x2\x2?@\an\x2\x2@\x42\ai\x2\x2\x41"+ + ";\x3\x2\x2\x2\x41>\x3\x2\x2\x2\x42\v\x3\x2\x2\x2\x43\x44\au\x2\x2\x44"+ + "\x45\ag\x2\x2\x45\x46\an\x2\x2\x46\r\x3\x2\x2\x2GH\av\x2\x2HI\aq\x2\x2"+ + "IQ\ar\x2\x2JK\a\x64\x2\x2KL\aq\x2\x2LM\av\x2\x2MN\av\x2\x2NO\aq\x2\x2"+ + "OQ\ao\x2\x2PG\x3\x2\x2\x2PJ\x3\x2\x2\x2Q\xF\x3\x2\x2\x2RS\a_\x2\x2ST\x3"+ + "\x2\x2\x2TU\b\b\x3\x2U\x11\x3\x2\x2\x2VW\a]\x2\x2WX\x3\x2\x2\x2XY\b\t"+ + "\x3\x2Y\x13\x3\x2\x2\x2Z[\a\x62\x2\x2[\\\a\x62\x2\x2\\\x15\x3\x2\x2\x2"+ + "]`\x5\x1A\r\x2^`\x5\x1C\xE\x2_]\x3\x2\x2\x2_^\x3\x2\x2\x2`\x17\x3\x2\x2"+ + "\x2\x61\x64\x5\x1E\xF\x2\x62\x64\a\x61\x2\x2\x63\x61\x3\x2\x2\x2\x63\x62"+ + "\x3\x2\x2\x2\x64j\x3\x2\x2\x2\x65i\x5\x1E\xF\x2\x66i\a\x61\x2\x2gi\x5"+ + " \x10\x2h\x65\x3\x2\x2\x2h\x66\x3\x2\x2\x2hg\x3\x2\x2\x2il\x3\x2\x2\x2"+ + "jh\x3\x2\x2\x2jk\x3\x2\x2\x2kw\x3\x2\x2\x2lj\x3\x2\x2\x2mq\x5\x14\n\x2"+ + "np\n\x3\x2\x2on\x3\x2\x2\x2ps\x3\x2\x2\x2qo\x3\x2\x2\x2qr\x3\x2\x2\x2"+ + "rt\x3\x2\x2\x2sq\x3\x2\x2\x2tu\x5\x14\n\x2uw\x3\x2\x2\x2v\x63\x3\x2\x2"+ + "\x2vm\x3\x2\x2\x2w\x19\x3\x2\x2\x2xz\x5&\x13\x2yx\x3\x2\x2\x2yz\x3\x2"+ + "\x2\x2z|\x3\x2\x2\x2{}\x5 \x10\x2|{\x3\x2\x2\x2}~\x3\x2\x2\x2~|\x3\x2"+ + "\x2\x2~\x7F\x3\x2\x2\x2\x7F\x1B\x3\x2\x2\x2\x80\x82\x5&\x13\x2\x81\x80"+ + "\x3\x2\x2\x2\x81\x82\x3\x2\x2\x2\x82\x83\x3\x2\x2\x2\x83\x85\x5$\x12\x2"+ + "\x84\x86\x5\"\x11\x2\x85\x84\x3\x2\x2\x2\x86\x87\x3\x2\x2\x2\x87\x85\x3"+ + "\x2\x2\x2\x87\x88\x3\x2\x2\x2\x88\x1D\x3\x2\x2\x2\x89\x8A\t\x4\x2\x2\x8A"+ + "\x1F\x3\x2\x2\x2\x8B\x8C\t\x5\x2\x2\x8C!\x3\x2\x2\x2\x8D\x90\x5 \x10\x2"+ + "\x8E\x90\t\x6\x2\x2\x8F\x8D\x3\x2\x2\x2\x8F\x8E\x3\x2\x2\x2\x90#\x3\x2"+ + "\x2\x2\x91\x92\a\x32\x2\x2\x92\x93\t\a\x2\x2\x93%\x3\x2\x2\x2\x94\x95"+ + "\t\b\x2\x2\x95\'\x3\x2\x2\x2\x96\x97\t\t\x2\x2\x97\x98\x3\x2\x2\x2\x98"+ + "\x99\b\x14\x4\x2\x99)\x3\x2\x2\x2\x13\x2\x3\x37\x39\x41P_\x63hjqvy~\x81"+ + "\x87\x8F\x5\a\x3\x2\x6\x2\x2\b\x2\x2"; public static readonly ATN _ATN = new ATNDeserializer().Deserialize(_serializedATN.ToCharArray()); } diff --git a/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.g4 b/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.g4 index 3c799069..c1b12f84 100644 --- a/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.g4 +++ b/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.g4 @@ -18,7 +18,7 @@ CloseText // match actual text Text - : ~( '[' | ']' )+ + : ( '\\[' | '\\]' | ~( '[' | ']' ))+ ; // @@ -89,4 +89,4 @@ Sign : '+' | '-'; Whitespace - : [ \t\r\n] -> skip; + : [ \t\r\n] -> skip; \ No newline at end of file diff --git a/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.tokens b/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.tokens index 561750b6..a4f4c855 100644 --- a/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.tokens +++ b/Source/AtlusScriptLibrary/MessageScriptLanguage/Compiler/Parser/MessageScriptLexer.tokens @@ -9,5 +9,4 @@ OpenText=8 IntLiteral=9 Identifier=10 Whitespace=11 -BlockComment=12 'sel'=5 diff --git a/Source/AtlusScriptLibrary/MessageScriptLanguage/Decompiler/MessageScriptDecompiler.cs b/Source/AtlusScriptLibrary/MessageScriptLanguage/Decompiler/MessageScriptDecompiler.cs index 44a7fa83..4b79ce57 100644 --- a/Source/AtlusScriptLibrary/MessageScriptLanguage/Decompiler/MessageScriptDecompiler.cs +++ b/Source/AtlusScriptLibrary/MessageScriptLanguage/Decompiler/MessageScriptDecompiler.cs @@ -217,7 +217,12 @@ public void Decompile(FunctionToken token) public void Decompile(StringToken token) { - mWriter.Write(token.Value); + var textWithEscapeChars = token.Value; + foreach(var sequence in MessageScriptLanguage.Compiler.MessageScriptCompiler.ESCAPE_SEQUENCES) + { + textWithEscapeChars = textWithEscapeChars.Replace(sequence.Value, sequence.Key); + } + mWriter.Write(token.Value.Replace("[", "\\[").Replace("]", "\\]")); } public void Decompile(CodePointToken token) diff --git a/Source/AtlusScriptLibraryTests/MessageScriptLanguage/MessageScriptTests.cs b/Source/AtlusScriptLibraryTests/MessageScriptLanguage/MessageScriptTests.cs index 83ba3da8..c4e48479 100644 --- a/Source/AtlusScriptLibraryTests/MessageScriptLanguage/MessageScriptTests.cs +++ b/Source/AtlusScriptLibraryTests/MessageScriptLanguage/MessageScriptTests.cs @@ -1,6 +1,9 @@ using System; using System.IO; +using AtlusScriptLibrary.Common.Libraries; using AtlusScriptLibrary.MessageScriptLanguage.BinaryModel; +using AtlusScriptLibrary.MessageScriptLanguage.Compiler; +using AtlusScriptLibrary.MessageScriptLanguage.Decompiler; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace AtlusScriptLibrary.MessageScriptLanguage.Tests @@ -82,6 +85,30 @@ public void ToBinary_ShouldMatchSourceBinary_Version1BigEndian() Compare(binary, newBinary); } + [TestMethod] + public void EscapeChars_CanDecompileAndRecompileWithBrackets() + { + var library = LibraryLookup.GetLibrary("p3re"); + + var binary = MessageScriptBinary.FromFile("TestResources/EscapeChar.bmd"); + var script = MessageScript.FromBinary(binary, FormatVersion.Version1Reload); + + var writer = new StringWriter(); + using (var decompiler = new MessageScriptDecompiler(writer)) + { + decompiler.Library = library; + decompiler.Decompile(script); + } + string text = writer.ToString(); + + var compiler = new MessageScriptCompiler(FormatVersion.Version1Reload, System.Text.Encoding.UTF8); + compiler.Library = library; + compiler.TryCompile(text, out var recompiledScript); + + var newBinary = recompiledScript.ToBinary(); + Compare(binary, newBinary); + } + private void Compare(MessageScriptBinary binary, MessageScriptBinary newBinary) { // compare headers diff --git a/Source/AtlusScriptLibraryTests/TestResources/EscapeChar.bmd b/Source/AtlusScriptLibraryTests/TestResources/EscapeChar.bmd new file mode 100644 index 0000000000000000000000000000000000000000..879641af4984658bea54c9db6248019165f47fe3 GIT binary patch literal 28215 zcmd6wd2l4xecv0yW2q4(QsPRKXo~6ukL3YC0QTf+NiMM1U4R6z-~xN`&~DF652hD0 z)1&E`#SWu#l!Ue^m7KUNl_T4-%}U9MB0FWeqBtr?NikJPMRD|poKhuBRT49@;!?^= zY$>)&sVG!Fzu$YWryFQcWHCyz#opeT?s>=W{f_VNc#pe0`O|)A>eT9z{?lvzrss|P zW&Zt(TqX0}^{<%w4ae-AcjV8Fm-XiD+HdclG54ER?EOV^e_PMqzhmy@pELKjAGY@| zoBPf7y?4x+&+qtwxxdrCf6J}r^DW;n_jf&G?(e?G-alsUx7qh@`;`6sEpy-fIdgxn zxp}wmHvf3vn7x1B-0!%_-oIwZ1+wt7lG@n1<+xutC{VvAAG^weLGLz z&U4RY^Zgz>kI@U}^XOO2{qAe_ZlB*{`@i>k^ZmU&bH8ui-al{dd+q1F|K5DQf6dSIVJ|DHukAB~Le#Cx$bieuh=r_#$ zF+09vw%wVJo9|~VU5+=*=eeG}f8E?q{G7R;^zHpO&Ha>ZZ~lJsdHy@*zHrRmZ9k8H z+msZSu*|+zvnEPq_{mP{Iyz()7|F*e5Y5C+yJC8H={WF%% zt8?bPRZEAp!{+natLA>z&g0yo`F!r{=6>F`d)~fxVa$Ag;YD-5_&$4o+1#J9{XF$0 z^ZDsDbAP5|@2{BqvoD(aM=ZTA+0U0J&G(lr-2&Tx#g4oBS@XQ+b06`%ntfh>)qKBh z$G84D^SN=ey<2)UzRzcV7s+S2)Blxu{{24lp64ws&s|!aSzSAS`pn#=<%Lu8b_U+a z4}a)+*Z+X`W?%c>4L|(hYu}xjn3!1T?M?jkxYrBYelzHW6aIpqG~#}FY`eAxuM3tPHpWcXtv^{=eMKvMz0sO z-f(Bq*W~2EOOux@d1+k#lw?jfK-(K{2OD&74--1mcS zH@X`7vMQ~p-S35o9|qm#K$aqEb>eO>X!rb981|y}dh(d8iEC))h`$_9_!nu#EadAp z7Brh_Gh==`?)g{xEYYx!xE&_hHJ_Y3ynRl(=DUQKkGNsv)?f_^^}11YV~`nonO>oxlLwCiKRuSe}DX|NJOJJ}4o5W^4PSSCCGBCHM3w{$Cw`r^;9KiP*VY$WgxEuOGuh$K#Jz12XUGuwP(g~}*u$B&9 z$36vzZsk#>%}qVV{gCT5N1M@eQMcC*n*LlA_8ea#U&23AQ`_4siQM0WUVNKRn}64} zxg2kfDeLs&*slg{zY)k-{iGSS{7PIKD09dCo;(mb!AVKKUWY`zMmO%SH~jEg*sVrM zxF^d_C!=oC8)NkX75%~wkcD2<3;oK#Z^rS4u0qeRH2a}nkK>xQ z$5>ToOioR2pOez)ZJ*_pH8-EdVMD^BB4cTT2;I05xN?-pI!TYLR5MOku0c8=w>V~P z_HFN1`Kr9z^UBBRd*J%c@YQC}t2T5(b`V#iS{NIN$h;ngO}`m!glNwU-CJRIth|+d zbS;8r7wtN5159bNf2T2inK6Ew*M8Dj4zoY=kg3%UbRQO;z+$lZX9UBzzH~VXBQl*dCRa>Hy`-1KYZuF|E;)LI#fEaV^n8>W< zPPX9fuX^6iw=#yGcVk%a*HPdMK)OLU$dHn#)yLSO)RhW3jgX_OvxTs~s@@J{wyFj~ zHi8~P)ofxFSb5>ln7_J1qQMKDPG*tK*o$m}*s+^G$Avxj{%) zM8S1KGy0?vb;?R8`D!?d7}uZ9EU zr!1@95=K#55L85K1nq&WL_6LbGOd|Ufjv;UdPmdq-tjBU=Wn?Ae{DWyp#+(^X6WJ z)PmBAz_o4}QR|_HRnxdAHug#XN5PG}o_t-n(`IR#)A8 zax@)X4BG2`mKJ47M<;@0u$48}beW;7k(;i}Gj7AqwJ2!DqI3LC5Ou?v5l}QouMcX# zAc9HYn?#lbt9mtTI_>I)!i4Oc+&6Rv&&R!BJqGWfbznf%;Yt^s+%B&prmX<95KF^| z8qHQku+UDGK8UMp2W{>A^iKBnUC%@NZ^BEz;yOQZ63Iqc*GErcY6|cN|o>!*b z9P<3LD!enRm}yP^rVGbF(yrLh=|UTNz309AMP6yScF&7TB2zOGt2m6-4Ax6=p1go@ zV1etbOhWH_{Ih@|zUS{w|GDRy@Sd7qVy=Riz6QNxa}qSPU(za)Abjg1gj%C zek6_fqe|}O@LJEGi{tL7o0M6}y$N!tEdH!s>+z-YGjB0(5Bzrh8~)My$j zs0$G${bnx@0cZPQV?p=sS_Akjh~2K=R#526 zl9la`0T^OJ!GyS@z=c{j*aUTG2YF&Z#yvTgbPeuA&2<`LH?3uau9aZ3SvIs-;A>QT zBy#CSE6rp*kp)$2IwlnW;UrlP8IK!B**TT6ZkuR9LAVM6#5GB_`kMO+?Co`8E8aWC zwZZjI;g3IZ^jZ*K5!s?&A|e9%tZP!XWMCadZANXL_dsEJxI5j9X(BZ-kh4qFz+*H<4kWq#q9O#!U>y4N94Ii0j}#Vg=VaIKyEZgwzOIcR?NbuV z*vfDCAg{x1xFArp7Q53@PP|8 z6Ep#56_CxydX{+MKv15n1jK3$j7X{;*;jxo6z9HgjquywgC2j&(E}wCRuMcgjnb5x zj(Q9ofCBVy4$4?`@g|8k;E0Ku55SJij;waC-;28di7kW91NgWipqAhF+nWMKp%d{6 zU0S!|zQSVR38!4lTncQn^8Neo@x1plpZEU;^Z7$JpZxl+!b|Z+-#<>+pdD2qcELIu zUvoht5gBe2YS`bGg+*f_kcmDh&0%k2!ZwL^VKZ`ud7vKyMTBj`|B9HO9DP*pKY8Py{|qfkT96GW8yYTcs77paM(cRP&J3}|9Qe{gZ`(V5mkN0uOiHc!>%3=|_%#9vUSH|f>yNlsWSI^L{BPFC`oLU1CX2vLP%9t7Mp!x}+Sv10=q z6*xcw^1ifbsI+=<_0r>~XP0J{Ph89edz3~Wz!rEbZoF$StN7jG71!~$#S6w?Ho{Lx z)o7t%FIVD9B8CY=N!UC{2&0OKSUMHpV&&rx5dZzaAJcE!^_%D8bK&}W6#6HLU4X7u zqgH`h+HQVCCzowNh*bs?CqnLOH|`8|rt)bKHulIn+_l1(o^@kd!AHS2GnS<4yVcYKW^VeL2wO zc_J6*PMkWiHZ!|;A}bgw7rw+lFS@bjIMXM9=Y{)hQ4WW4R4N4N==Ju8}Z2cn6&!aZhIk zM9dA%TH178W)2kK>k*H*%bw>M<))>;^p>izXO;QB!|_cB1cKUt`Yb zi`B3zw;B>@fkE7q4L=+xuw}{*qkrmocaPI&Mt%|zb|(T75oaP2;w@WuSE!3o$gZaw za9)fw)1hG%Y$3`eD2vmq?6DvbJdG&H=mmbd#PQ0>rAzZGXIHjqGF_v)KgU=Px$a*3 z-pJh}OTjgN9#b=N=g81r2yEi3i4orAfiWMJ7CYJ5yMN$$_e{|KPo?eW^27@*4fq)e z(Wp&f7A0dsoJg2ClO@))LYR~-?fBkcTYLfHLC)c~qeYg*t{f<^cOxFL%6kO=JnhE1 z3~5b>4voqRr3l}(>YL1zs#)nzQb8glny(Yv8&xCmJ%C?sEsVSr*){R^?!BM>7hV4@ zKq&e=)02&B5=+y51V4!4l#Bt;5H^x30@tDGZ`;aKjivpu_V@k?eg1~)^CaM2BiaHI z1k_pn!vKWW8UeTyq%1I^&J)s98bTy4X}m5+m>ms)OeMcEz;H&4FI7%kb97F9XRGEM z4IMvk)5yxt_u((UDSm!8Zc4BVd5A0@K z+x711j(YdNHaxKKfwmo;W!+nEk--IlTCgQ?DOCsK#R0?Badm}I1(|k!c@0F6dmuFN!6E$s7P^^ zs8yr@f38cBMI=Q@B3M*$Yza)~nMN=cVF!YKwCnU^S%Bt{d+HQ2ZDk$?>-cAz_E!FR zXzfk%&vv_gu)uDcw($Wx^rER*%kj+`L^|7w`Xs{fJXv5uW`un!3DqdWk;5N<| z9aZ+cv0G_>pKE{V#M11EGpqjT<;9Cf{1exz&3>Y#SOh1Q4M}qF=J8wp)$k*{S9XT8x&oykIfL?;X4ZJc#U_;*`+ah{={Hu)T zgd0yLN~Pd4=~t_0a|{=e)=DTH0WiXYbvHKE-h>1WR@3e3k&_TnwtbTl0c5Ua0&5`Rd*azJB=BoXnd#W>3f zH{)usMQg4xDJ|&ihGMpfF7-P#6ZDS3g(f+tfgJ{}ymhF+Hja32XKuv6hFJ6Is7Urp|D^h_Xp@x}O%R>H0jUb7Yt@FG9Q zsUI}5#x&wHrAwrS38nwZDF16-fv`W8HRhnwqL(;rK5+-_=> z>~ZWsJJeKPMup&omiz70B%?t3Emb3@!i|l%zX9Fm`FW05YoatXCfp<^DNIahvlbSN z`J?-~HLYt)%5*%~Gb(N_U!TW~sF5|%w@JJLWa8dqTfyV17CvfyrtnZZ+$27TR@|zj zj7%5#!`?eQZ@<{T!;XG4rXEfU18I{?+<-b%r|WI~83~VWr~+u$sQ@deKH4w(4@_Nv zady&2&S>*PGwuSry~`sOc;F_kr@4NO>%Vy3!H2mvxqcUZc*XS@xIagr56MI^CN?Yw z$0k9OB->^KE><~23t(U+V@Y{2U<+-aVeFi;S;cmsrjH=3NwBG&yp#|kw!}CE0GP@p z5dsX1i6V;X%IdgT;;%>iQ&bVlvJoO%%MhEf7>y~gNst*?Gz<}vMvfihtSG`wkO)Dd zYD>!*5k?JCcZiG_+ok#m@W|9mP>fVYH`HP^Q?(Usk!>QC#GEm&j^q( zE+31JW!yTNwXjVkmlVi$t?oueZbBTh-!xg=SGtISN{ zk6K7L!W3O9)8{06DH!nnP#J3Fgc{d!TZ(qn`IquUU4tQGEB-sY6D~URb;J?5JbamX z{E1uUx2V?!C^6i_fp4=(r{H1aV3v|T)ha`j#NtRrv2v3@R!WKGRg_k4?!vDXeocLx zB`|ESOhWot%$iB|64TJqWa65e_-BH0U`ukA3J z3$Uij+7Ynek$=u>JKzlT+Az^1Yf)>8<)d!YI)tg52@db{yVTfH$&@AL76DUoB8D9a zlgmU&U@=jVHKnJ48mZI`=S%7-ov*%`vYXCvYH}x8{O~iL_hI(ce)!wW^Ite#drPt? zf-~Bck_!9~>(h$}VgcY!BJ4d;LTC)i`Ee+1p^L;8!5T58S0+O1#zJ$V+2w+)QWzvD z*K(@iCA5bblef}Ii;PW87RXr1BW7@Pk?U_V->&Q9=`$zhW{$6&n0xjJ+Rl^^hN2{z zCUb@SieMX^fyStWU>rhr)c-ly>Y9>$B;qFbWJ8{m`(lff6uRz~=cXnLcuw)eQLvtO zn`?{-4d=vOx~a(mzeRcV5#RG3sq@=kb-$HmkfDs%VMhogbfUCb982a>7M662L@~1D zkeLw(Jx~2v!c{VL>NGTtY)yZE9rdQQ+$=?-kNJ*z5`ahlY$;hoQ&LhoTpG)d1=wEa z|A@>#%`fKoP-~K?@T5q^ITgx4a8g-Z=C&mL2pVklooP_yd}^`)Yb)&@MFt-IEU#@k z+ATPnDqQNQWLa6GZWX~;NdvDy%HDD!omxxaZJMVpOI@kprcPk}Aray&Yg>R{&G>%c zd5?kpcBlh-(=i0$3~~z_QuDDqxTdnnjKya*D1tbG5lwhx81*Mbq|qpTlJc_3Sphb_ z&U+VQ{xa8hJ@43g#{S2Sw$i(C{!m{MvrK%l1F8kgwl-lm6oqUy%@LO9l+yxID$fQr z!Wt5@0za~ktuJCHxn&7O)g{U*4BcW|T-R1F!yKmSLF+iB;IzwDlYTy;OhK>^Wt<%z zfyrcGo;GEO!V6M=zx6R$CwVMUAtO7E-wJTO#)Xc7e`fCDnuIRD<>->~971Fw!rG%i z5D_eDn^Bu^oeR}qKLx}~eKJ@x0_JB83q!G^N!!Papa$SUw66q22I|+ztm@(rn(_b& z?Zla9K4^r;gLa=VyuWXXsth+b7f(KL3H{0h(myJ{GoR=4TgpdFJzSt0)F+26sV1fr|PhSkKoMJOdBJ6;RxTGwE6w(`Z#j>-c0>!nKwyl6?OZ#pko%*9h+FaEgE6*Osq&M!;{n}Hy&Z;vXF3?HJ!^iP^ zkN-Q*n|p}${(~Wpxwfc?jW;Q|Gbv}7shspHwZ6#q)hK48kvLj4Dw%3zH1ZNS+|Db! z={7V|EeB=5-(tMvfubxrU`EI}6@&a6AIwz$=8c#`S>mHfk%Wd?({3mQRK1~6AYlxD z4H^Yq6ocb=sU4asit{SZ&x!3wV*nCkc10SQ!VHCWGp!0K4+UuI;)?7TIv40r)%|nd zCsa-x$os6L@mu3{n9ZLtar=2O+x}eGiqRtAWVHk8CY9Bd%(zKHZ`u9|B-)fZ`3^pY z%~xp*W9s1oT{q&ro3Ve1v0rgx*Dg&NqbN6gCsEeYq=1VsF;%C^>U=9+xw17&VkxQN zT}cg4rFIo?C82KEg0@Y7e1^-lL|Up}*_a}BjzwaY zs<@S{@VrT0NFAc7=Y{PXCfoo-<{yoI_jOWy zZgK&4?3GT%LUS)uMKMgJ^{JPbTZ*X+?<+=BI~KMHKr&a-P7+9GpFU7p=S;niec9y{*^Zi1*pB}$C8jz+ZLMEGF3&Nt3%vNc`kD|ok2 zj&>{KpK#-UdhPVw%*DN{{@Ur4h2zh%KbswpREQuvvk;dO$>I4Q(?x!SuGvD3HXn6u z=4i5jRFF?F`A*?-d%%JQQY7{;BI4c;wY2#c)Kkb?hz?s{T5*e2}Q_eeypes>Swrmn)4Eo|-OQfL-#Le;iPJYf4 z=)NcZ3gb&-hq?8A)3|9lYF`OR2XL-JU-{by!w$U&lo(EC7_GO(*(8lXL=+X(31gg4 zbw}-j6MDN6q)acq`*hKnF(ck?QjOO${&B}QjGz;9Y>E!#4Apf3F&4I@)9si)Jw0t% zUTy4j(U~sF^NSZ~bKSL>r%CD)xp9jNA{z^2v%1CuOpaO<7c$YrZPCdXDam9bQw}oo zE3}vIVSe9YEE{et?f4Sy@t>We)E0}kp+z&p0v3QJ>aT|RG_n1}AFcO$K{y^&`Ww;M zs6Q%adk}5rpXwAzg_6TIMpg^#rON8kH4uvIaY)ZLkdhms=ZFfG3Ua~@Gf#`HvL!tV ziVZmgb-8SGdwpE?HLIlsClj;HIWAkVnkW{5cHKS@axSGT`|Gd2GL`1MQ)$O^u7Z5G-G>} zv5_P!z$V7`kZ@V*fJgw0FteD;QSx=Vi)>=FyvR-~@)l-4HaS_zOc1fMK7-Z>Nep60 zFXhL51@tO;97=bZ^*{Zu7}q~^<66trkBGK(y&EjF88)?MgEfvmoPk1bCd| z;=TfWtu$X*V{Z4kxk*+McVFtXoVAOEwM-_^VD;%8>(p0Xq^)_^R!)zYT%ejy6GVLN zdvhZrTJ^Sd@NQ*PE(`0?1;0FrFYG<>#`+S%u(xO9b-Ob<@?e1;P&z&NG5Wjo#`>G> zbKC=k9>h>Is#snkq|o1p-REuV<)&=#&i;Z}^@#8yJl# z1r8qZ_uX5jMjzdzCmB(GDq2dTB$~UBAcq54O6Q_IcslPhJ^D<~nplI9t`kDPE-^%H zsT?oUqg$DZF80tRkX4uN!4tabS-w0_fRRkU-=W`gj^1yzU&jHtITzKxY2T|2`c8ee zx7v4>8nk(Y<|%`J6-oxd|>aGqlK(HNh3{0hjQ*64)+$tAaQ7?IM|bEdNJ#~ zQ~Z4GGDlc_l72q!`T@&WU8{?(onngEALeYQdvo5L%Vo=YF%f`z#zcx@sI11!+M9}D zbF`F;Y)C-^7TgJek^3TjEOLLA{O{Rm#`)J=?{9gWIi)(LUZ7|TTimSMM0Oae)fojm ztk~h~ml*4RWURmN;~Hz0w-niAcuU9sx|Bwr3*Q|m#A4{1a~;NhIURf5s1CIbrgDIQ zQv#i&213q{fGauQ2bqgEoBCG#qHdwvr3)llUaL3I+ov(VS?Db16U?_H~?N zLSo|Z;e!w@limGN*d@7Jfz~MmGBN0)`f-i*KmBpGv;8NIF{3WU`>$@CIl7=l+*SwSg17@jhNFh>d*jl@9ZJ$BaGbf`UsHJie+J0LV{W9z`po<(s8zd%597M8_Yj-u)rQG zR(j?$(B!!5B1aQ*n22>5P5jj9>NG#pqO#wDAklkMhjzjzQttZf3I2M~^`&%?dTPoG zgyap9cvN!X+6%Qww{WI|Jdx^Wwv9@PPtF(InrqScnBXPZisu5uVkVr;*GO2IjsJ2; z1SA@UXR&+PY=8|Yn0XY`Uf|X;hi`EG56}C^EY}NMzeFDIb~mR{Hvda-h>{-GmCjD# zyK4DX=A2wz$6T0cT|HclE-jSt--y=hX*7}xl8`LSZpo2jh z%L3k0oqlOIF4+t`k)A)16j1J+4D~!l@tR?u>w?)^kA975f!&_ zt(p{q$tEh^(4uHfzWD6B?{^F%3#OVnRD@?dbloMff9YP7nFsvQH6bbW=0T0<)GS}j zxcHWCIN{6Ve7Ve;N_-8~g`g7@;)s$_e~u@sQWs`}iblF^_KIMLJDXzaP!X;Xe!RTK zc$OUhrS!Xl^QVab5YR_&aRL_Sgjhz|fh0q(fcA_&EvkRib-PUbJGg__KH>T`(O?Of z39D$q3sJsnIg};c z6p@a(K>w)R2A^Wg?2D*SqgaW!{t|L~%JrDiP0#HpKSA%6X&b^~gevNfGSn z>giZx8uTZ!FJG7SYdu`eM3ux~n1GLYLNaoXuCE)ys@A~5zUX#)92yR{Zu1v&N5YI1 zEUyz6l9i0R9Au&a$~sSp6qsOD?l5rIa)E&3eG(&*~xc+6jMF zUuF*fnmMHBtrU_q5Sof~YjKi|2bwy%GN=MYOi|$$Z(sN&rKFL)>8T?9Bl2FGV+_09 z(w?MRv~TOKS5GW5{sKKgJs!W|PwlH*|Jn1x>$y0WDLllr%GKohDX!0R{S&T#!}S-Q zS0_JLALlyF)#f6;Q2%u<&ZaB9$Bp44n<}~y$YUd{1h4(~U%rlgeV%)Gvd>fMSLIj$ zim!OQEBjd8-EQB1f~}!fVxHcZeLBNAy$N65l>Kr|3Q?9cr`+Y)M(!CaEoCqApq+hi zyotL?jd93>diKGpoI*z}$8k~u)u_qi_3UF50D&>-k|$TPPoxInc(Y&O`&RaQe$h_k zY;)T(&p(=dewxrModFVf(#SqJ6I~VT-D@<73h}U)eRwMBQZiuVZ&d@(yb)*LnA6?H z#F7wB$iw5S*~h0)Q)F47bbFm={p_<@2`>_MBva3$ZuZgHc3)kBB?2luOR~>QX^}!4 z9yR5W{89gR$Mb~O;k`HE|B6f&ovW+ZbzS`5)X#ATXd3C09Ss`kQ03C*Xla2mQVt0I zTD)w~YHL9BNA_KStF`aw zPWn!DD_dsFIrS#-CNs;0h15`S`nlQNVUE1gT4nS)Wvj3NE}LekvsH}*E<{Hb%|HGB zGDTnD|84U7j3xDnX6(L1yHPq-?ot~os43NT7sH@oUlOZ2K_jNW0)9&SyYfCl)lwTf z>F9peVb@IJNvc`Xe&*zySbpJMVXRmFG1u>L{Rb{;RX1+nA~v*fKNsz8EOTAv8gRY9 z^=n+e%|%XZ+m;W*m~HvzO_8IQ?q%#_k}n-LtbJ>3M5#a;9`yKkrb^=FR`8k{oY2 zTfmV2WV+iSdFid{|1<_By#D{wKc)BXKUlg@YD|`%xxdsnT3RWcIaYe6R4+aC__5OE z+rLt(j6MG7Sm~+TzqsqCZ~5s`ZP)Xq%cZA|9xh!tQhI#0bft9eSn14>*~6uC6a4dV zsWDMndHiT;ae@~c6O&`5`uxF1ceM{s-u`=~&MhxaOzeHFba~e&Z+W@Y*>$zFcxS0{ zq_kXmYS#<9u1wtW@~*!+QToXI$x?f{bos&QQd4dx=S%hF$4l+|4j!I8a`e&p>C&0f zTInORb946{Ia)e1dw6BnC-;{sxBqJC!u*lah1-9J0nXm_Gmn(+JAC-?qjRN$r8|GC JEK+R${BJmqX3qcs literal 0 HcmV?d00001