From ccc2156cf91ffdfb9a5d863e8570d1472d941475 Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Mon, 22 Apr 2019 15:50:14 +0300 Subject: [PATCH] Add parsing for assignment expressions (PEP 572) (PY-33886) Highlight expressions that are invalid by grammar or unacceptable in runtime Highlight expressions in pythons < 3.8 GitOrigin-RevId: 89acec9db5b3a931da31c33778185e147240ec01 --- .../jetbrains/python/lexer/_PythonLexer.java | 1162 +++++++++-------- .../com/jetbrains/python/PyTokenTypes.java | 3 +- .../python/psi/PyAssignmentExpression.java | 26 + .../python/psi/PyElementVisitor.java | 4 + .../com/jetbrains/python/PyElementTypes.java | 3 +- .../python/PythonTokenSetContributor.java | 3 +- .../com/jetbrains/python/lexer/Python.flex | 1 + .../python/parsing/ExpressionParsing.java | 53 +- .../psi/impl/PyAssignmentExpressionImpl.java | 46 + .../validation/AssignTargetAnnotator.java | 36 + .../validation/CompatibilityVisitor.java | 7 + .../invalidAssignmentExpressions.py | 23 + .../unsupportedAssignmentExpressions.py | 13 + .../assignmentExpressions.py | 13 + python/testData/psi/AssignmentExpressions.py | 17 + python/testData/psi/AssignmentExpressions.txt | 186 +++ .../psi/InvalidAssignmentExpressions.py | 10 + .../psi/InvalidAssignmentExpressions.txt | 81 ++ .../python/PythonHighlightingTest.java | 10 + .../jetbrains/python/PythonParsingTest.java | 10 + .../PyCompatibilityInspectionTest.java | 5 + 21 files changed, 1123 insertions(+), 589 deletions(-) create mode 100644 python/psi-api/src/com/jetbrains/python/psi/PyAssignmentExpression.java create mode 100644 python/src/com/jetbrains/python/psi/impl/PyAssignmentExpressionImpl.java create mode 100644 python/testData/highlighting/invalidAssignmentExpressions.py create mode 100644 python/testData/highlighting/unsupportedAssignmentExpressions.py create mode 100644 python/testData/inspections/PyCompatibilityInspection/assignmentExpressions.py create mode 100644 python/testData/psi/AssignmentExpressions.py create mode 100644 python/testData/psi/AssignmentExpressions.txt create mode 100644 python/testData/psi/InvalidAssignmentExpressions.py create mode 100644 python/testData/psi/InvalidAssignmentExpressions.txt diff --git a/python/gen/com/jetbrains/python/lexer/_PythonLexer.java b/python/gen/com/jetbrains/python/lexer/_PythonLexer.java index 8ca1155f85d8..d97f2edd2869 100644 --- a/python/gen/com/jetbrains/python/lexer/_PythonLexer.java +++ b/python/gen/com/jetbrains/python/lexer/_PythonLexer.java @@ -194,27 +194,28 @@ class _PythonLexer implements FlexLexerEx { "\1\55\1\56\1\57\1\60\1\61\1\62\1\63\1\64"+ "\1\65\4\3\2\50\1\52\1\66\1\2\5\0\1\2"+ "\1\67\1\0\1\70\1\0\1\3\1\67\1\71\1\72"+ - "\3\7\1\73\3\7\1\3\2\74\1\75\1\76\15\3"+ - "\1\77\1\100\1\101\1\102\10\3\1\103\1\104\1\105"+ + "\3\7\1\73\3\7\1\3\2\74\1\75\1\76\1\77"+ + "\15\3\1\100\1\101\1\102\1\103\10\3\1\104\1\105"+ "\1\106\1\107\1\110\1\111\1\112\1\113\1\114\1\115"+ - "\1\116\1\117\1\120\1\121\1\0\3\45\1\122\3\45"+ - "\1\3\6\47\2\0\1\123\1\3\2\0\1\51\1\50"+ - "\1\51\1\3\6\54\1\3\2\124\1\57\2\3\1\0"+ - "\1\50\1\0\1\2\1\0\1\2\1\0\1\2\1\0"+ - "\1\67\1\0\1\3\1\0\1\7\1\125\1\126\1\0"+ - "\1\125\1\3\2\0\1\127\1\3\1\130\1\131\1\132"+ - "\5\3\1\133\6\3\1\134\5\3\1\135\1\136\1\137"+ - "\1\140\1\0\1\45\1\141\1\142\1\0\1\141\1\3"+ - "\1\47\2\143\1\51\1\3\1\54\2\144\1\3\2\0"+ - "\1\50\1\0\2\145\1\0\1\3\1\74\1\3\1\146"+ - "\1\147\10\3\1\150\1\3\1\151\3\3\1\0\2\142"+ - "\11\0\1\3\1\124\4\0\2\3\1\152\1\3\1\153"+ - "\1\154\4\3\1\155\1\3\1\156\10\0\1\125\1\157"+ - "\1\160\1\161\1\3\1\162\1\163\1\3\1\164\1\141"+ - "\1\143\1\144\1\145\1\0\1\165\1\3\1\166\1\167"; + "\1\116\1\117\1\120\1\121\1\122\1\0\3\45\1\123"+ + "\3\45\1\3\6\47\2\0\1\124\1\3\2\0\1\51"+ + "\1\50\1\51\1\3\6\54\1\3\2\125\1\57\2\3"+ + "\1\0\1\50\1\0\1\2\1\0\1\2\1\0\1\2"+ + "\1\0\1\67\1\0\1\3\1\0\1\7\1\126\1\127"+ + "\1\0\1\126\1\3\2\0\1\130\1\3\1\131\1\132"+ + "\1\133\5\3\1\134\6\3\1\135\5\3\1\136\1\137"+ + "\1\140\1\141\1\0\1\45\1\142\1\143\1\0\1\142"+ + "\1\3\1\47\2\144\1\51\1\3\1\54\2\145\1\3"+ + "\2\0\1\50\1\0\2\146\1\0\1\3\1\74\1\3"+ + "\1\147\1\150\10\3\1\151\1\3\1\152\3\3\1\0"+ + "\2\143\11\0\1\3\1\125\4\0\2\3\1\153\1\3"+ + "\1\154\1\155\4\3\1\156\1\3\1\157\10\0\1\126"+ + "\1\160\1\161\1\162\1\3\1\163\1\164\1\3\1\165"+ + "\1\142\1\144\1\145\1\146\1\0\1\166\1\3\1\167"+ + "\1\170"; private static int [] zzUnpackAction() { - int [] result = new int[352]; + int [] result = new int[353]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -242,50 +243,51 @@ class _PythonLexer implements FlexLexerEx { "\0\0\0\114\0\230\0\344\0\u0130\0\u017c\0\u01c8\0\u0214"+ "\0\u0260\0\u02ac\0\u02f8\0\u0344\0\u0390\0\u03dc\0\u0428\0\u01c8"+ "\0\u0474\0\u04c0\0\u01c8\0\u01c8\0\u01c8\0\u050c\0\u0558\0\u01c8"+ - "\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u01c8"+ - "\0\u05a4\0\u05f0\0\u063c\0\u0688\0\u06d4\0\u0720\0\u076c\0\u07b8"+ - "\0\u0804\0\u0850\0\u089c\0\u08e8\0\u0934\0\u0980\0\u09cc\0\u0a18"+ - "\0\u0a64\0\u0ab0\0\u0afc\0\u0b48\0\u0b94\0\u0be0\0\u0c2c\0\u0c78"+ - "\0\u0cc4\0\u0d10\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u0d5c\0\u0da8"+ - "\0\u0df4\0\u0e40\0\u01c8\0\u0e8c\0\u0ed8\0\u0f24\0\u0f70\0\u0fbc"+ - "\0\u1008\0\u1054\0\u10a0\0\u10ec\0\u1138\0\u1184\0\u11d0\0\u01c8"+ - "\0\u121c\0\u1268\0\u12b4\0\u1300\0\u01c8\0\u01c8\0\u134c\0\u01c8"+ - "\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u1398\0\u13e4\0\u1430"+ - "\0\u147c\0\u14c8\0\u1514\0\u01c8\0\u01c8\0\u1560\0\u15ac\0\u15f8"+ - "\0\u1644\0\u1690\0\u16dc\0\u01c8\0\u1728\0\u1774\0\u01c8\0\u17c0"+ - "\0\u180c\0\u1858\0\u01c8\0\u01c8\0\u18a4\0\u18f0\0\u193c\0\u01c8"+ - "\0\u1988\0\u19d4\0\u1a20\0\u1a6c\0\u1ab8\0\u1b04\0\u01c8\0\u01c8"+ - "\0\u1b50\0\u1b9c\0\u1be8\0\u1c34\0\u1c80\0\u1ccc\0\u1d18\0\u1d64"+ - "\0\u1db0\0\u1dfc\0\u1e48\0\u1e94\0\u1ee0\0\u02ac\0\u02ac\0\u02ac"+ - "\0\u02ac\0\u1f2c\0\u1f78\0\u1fc4\0\u2010\0\u205c\0\u20a8\0\u20f4"+ - "\0\u2140\0\u01c8\0\u01c8\0\u218c\0\u01c8\0\u01c8\0\u21d8\0\u01c8"+ - "\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u2224\0\u01c8\0\u01c8\0\u2270"+ - "\0\u22bc\0\u2308\0\u2354\0\u23a0\0\u01c8\0\u23ec\0\u2438\0\u2484"+ + "\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u05a4\0\u01c8\0\u01c8\0\u01c8"+ + "\0\u05f0\0\u063c\0\u0688\0\u06d4\0\u0720\0\u076c\0\u07b8\0\u0804"+ + "\0\u0850\0\u089c\0\u08e8\0\u0934\0\u0980\0\u09cc\0\u0a18\0\u0a64"+ + "\0\u0ab0\0\u0afc\0\u0b48\0\u0b94\0\u0be0\0\u0c2c\0\u0c78\0\u0cc4"+ + "\0\u0d10\0\u0d5c\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u0da8\0\u0df4"+ + "\0\u0e40\0\u0e8c\0\u01c8\0\u0ed8\0\u0f24\0\u0f70\0\u0fbc\0\u1008"+ + "\0\u1054\0\u10a0\0\u10ec\0\u1138\0\u1184\0\u11d0\0\u121c\0\u01c8"+ + "\0\u1268\0\u12b4\0\u1300\0\u134c\0\u01c8\0\u01c8\0\u1398\0\u01c8"+ + "\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u05a4\0\u13e4\0\u1430\0\u147c"+ + "\0\u14c8\0\u1514\0\u1560\0\u01c8\0\u01c8\0\u15ac\0\u15f8\0\u1644"+ + "\0\u1690\0\u16dc\0\u1728\0\u01c8\0\u1774\0\u17c0\0\u01c8\0\u180c"+ + "\0\u1858\0\u18a4\0\u01c8\0\u01c8\0\u18f0\0\u193c\0\u1988\0\u01c8"+ + "\0\u19d4\0\u1a20\0\u1a6c\0\u1ab8\0\u1b04\0\u1b50\0\u01c8\0\u01c8"+ + "\0\u01c8\0\u1b9c\0\u1be8\0\u1c34\0\u1c80\0\u1ccc\0\u1d18\0\u1d64"+ + "\0\u1db0\0\u1dfc\0\u1e48\0\u1e94\0\u1ee0\0\u1f2c\0\u02ac\0\u02ac"+ + "\0\u02ac\0\u02ac\0\u1f78\0\u1fc4\0\u2010\0\u205c\0\u20a8\0\u20f4"+ + "\0\u2140\0\u218c\0\u01c8\0\u01c8\0\u21d8\0\u01c8\0\u01c8\0\u2224"+ + "\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u2270\0\u01c8\0\u01c8"+ + "\0\u22bc\0\u2308\0\u2354\0\u23a0\0\u23ec\0\u01c8\0\u2438\0\u2484"+ "\0\u24d0\0\u251c\0\u2568\0\u25b4\0\u2600\0\u264c\0\u2698\0\u26e4"+ - "\0\u0f70\0\u01c8\0\u2730\0\u1138\0\u11d0\0\u277c\0\u27c8\0\u2814"+ - "\0\u2860\0\u28ac\0\u28f8\0\u2944\0\u2990\0\u29dc\0\u2a28\0\u2a74"+ - "\0\u2ac0\0\u2b0c\0\u2b58\0\u2ba4\0\u2bf0\0\u1514\0\u2c3c\0\u2c88"+ - "\0\u2cd4\0\u2d20\0\u2d6c\0\u2db8\0\u2e04\0\u2e50\0\u2e9c\0\u2ee8"+ - "\0\u2f34\0\u0390\0\u2f80\0\u2fcc\0\u01c8\0\u2f80\0\u3018\0\u3064"+ - "\0\u30b0\0\u30fc\0\u02ac\0\u3148\0\u02ac\0\u02ac\0\u02ac\0\u3194"+ - "\0\u31e0\0\u322c\0\u3278\0\u32c4\0\u02ac\0\u3310\0\u335c\0\u33a8"+ - "\0\u33f4\0\u3440\0\u348c\0\u02ac\0\u34d8\0\u3524\0\u3570\0\u35bc"+ - "\0\u3608\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u3654\0\u36a0\0\u36ec"+ - "\0\u01c8\0\u36a0\0\u3738\0\u3784\0\u01c8\0\u37d0\0\u381c\0\u01c8"+ - "\0\u3868\0\u01c8\0\u38b4\0\u3900\0\u394c\0\u3998\0\u39e4\0\u3a30"+ - "\0\u3a7c\0\u3ac8\0\u3b14\0\u3b60\0\u3bac\0\u01c8\0\u3bf8\0\u02ac"+ - "\0\u02ac\0\u3c44\0\u3c90\0\u3cdc\0\u3d28\0\u3d74\0\u3dc0\0\u3e0c"+ - "\0\u3e58\0\u02ac\0\u3ea4\0\u02ac\0\u3ef0\0\u3f3c\0\u3f88\0\u3fd4"+ - "\0\u4020\0\u406c\0\u40b8\0\u4104\0\u4150\0\u419c\0\u41e8\0\u4234"+ - "\0\u4280\0\u42cc\0\u4318\0\u4364\0\u01c8\0\u43b0\0\u3ac8\0\u3b14"+ - "\0\u43fc\0\u4448\0\u4494\0\u02ac\0\u44e0\0\u02ac\0\u02ac\0\u452c"+ - "\0\u4578\0\u45c4\0\u4610\0\u02ac\0\u465c\0\u02ac\0\u46a8\0\u4020"+ - "\0\u406c\0\u46f4\0\u4740\0\u478c\0\u47d8\0\u4824\0\u4870\0\u02ac"+ - "\0\u02ac\0\u02ac\0\u48bc\0\u02ac\0\u02ac\0\u4908\0\u02ac\0\u36a0"+ - "\0\u01c8\0\u01c8\0\u01c8\0\u4870\0\u01c8\0\u4954\0\u02ac\0\u02ac"; + "\0\u2730\0\u277c\0\u01c8\0\u27c8\0\u1184\0\u121c\0\u2814\0\u2860"+ + "\0\u28ac\0\u28f8\0\u2944\0\u2990\0\u29dc\0\u2a28\0\u2a74\0\u2ac0"+ + "\0\u2b0c\0\u2b58\0\u2ba4\0\u2bf0\0\u2c3c\0\u2c88\0\u1560\0\u2cd4"+ + "\0\u2d20\0\u2d6c\0\u2db8\0\u2e04\0\u2e50\0\u2e9c\0\u2ee8\0\u2f34"+ + "\0\u2f80\0\u2fcc\0\u0390\0\u3018\0\u3064\0\u01c8\0\u3018\0\u30b0"+ + "\0\u30fc\0\u3148\0\u3194\0\u02ac\0\u31e0\0\u02ac\0\u02ac\0\u02ac"+ + "\0\u322c\0\u3278\0\u32c4\0\u3310\0\u335c\0\u02ac\0\u33a8\0\u33f4"+ + "\0\u3440\0\u348c\0\u34d8\0\u3524\0\u02ac\0\u3570\0\u35bc\0\u3608"+ + "\0\u3654\0\u36a0\0\u01c8\0\u01c8\0\u01c8\0\u01c8\0\u36ec\0\u3738"+ + "\0\u3784\0\u01c8\0\u3738\0\u37d0\0\u381c\0\u01c8\0\u3868\0\u38b4"+ + "\0\u01c8\0\u3900\0\u01c8\0\u394c\0\u3998\0\u39e4\0\u3a30\0\u3a7c"+ + "\0\u3ac8\0\u3b14\0\u3b60\0\u3bac\0\u3bf8\0\u3c44\0\u01c8\0\u3c90"+ + "\0\u02ac\0\u02ac\0\u3cdc\0\u3d28\0\u3d74\0\u3dc0\0\u3e0c\0\u3e58"+ + "\0\u3ea4\0\u3ef0\0\u02ac\0\u3f3c\0\u02ac\0\u3f88\0\u3fd4\0\u4020"+ + "\0\u406c\0\u40b8\0\u4104\0\u4150\0\u419c\0\u41e8\0\u4234\0\u4280"+ + "\0\u42cc\0\u4318\0\u4364\0\u43b0\0\u43fc\0\u01c8\0\u4448\0\u3b60"+ + "\0\u3bac\0\u4494\0\u44e0\0\u452c\0\u02ac\0\u4578\0\u02ac\0\u02ac"+ + "\0\u45c4\0\u4610\0\u465c\0\u46a8\0\u02ac\0\u46f4\0\u02ac\0\u4740"+ + "\0\u40b8\0\u4104\0\u478c\0\u47d8\0\u4824\0\u4870\0\u48bc\0\u4908"+ + "\0\u02ac\0\u02ac\0\u02ac\0\u4954\0\u02ac\0\u02ac\0\u49a0\0\u02ac"+ + "\0\u3738\0\u01c8\0\u01c8\0\u01c8\0\u4908\0\u01c8\0\u49ec\0\u02ac"+ + "\0\u02ac"; private static int [] zzUnpackRowMap() { - int [] result = new int[352]; + int [] result = new int[353]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -359,351 +361,352 @@ class _PythonLexer implements FlexLexerEx { "\1\12\2\0\2\12\1\0\1\12\1\0\1\12\2\174"+ "\1\175\1\0\1\176\1\12\2\0\1\12\14\0\5\12"+ "\1\174\1\12\1\174\1\12\1\174\3\12\1\174\10\12"+ - "\54\0\1\177\113\0\1\200\56\0\12\12\2\0\2\12"+ - "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ - "\14\0\1\12\1\201\1\12\1\202\22\12\17\0\12\12"+ + "\54\0\1\177\113\0\1\200\113\0\1\201\56\0\12\12"+ "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ - "\2\0\1\12\14\0\13\12\1\203\12\12\17\0\12\12"+ - "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ - "\2\0\1\12\14\0\4\12\1\204\21\12\17\0\12\12"+ - "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ - "\2\0\1\12\14\0\12\12\1\205\4\12\1\206\6\12"+ + "\2\0\1\12\14\0\1\12\1\202\1\12\1\203\22\12"+ + "\17\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ + "\3\0\1\12\2\0\1\12\14\0\13\12\1\204\12\12"+ + "\17\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ + "\3\0\1\12\2\0\1\12\14\0\4\12\1\205\21\12"+ + "\17\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ + "\3\0\1\12\2\0\1\12\14\0\12\12\1\206\4\12"+ + "\1\207\6\12\17\0\10\12\1\161\1\12\2\0\2\12"+ + "\1\0\1\12\1\0\1\12\2\161\1\17\1\0\1\21"+ + "\1\22\2\0\1\12\14\0\1\210\3\12\1\211\1\161"+ + "\1\12\1\161\1\12\1\161\3\12\1\161\1\22\7\12"+ + "\17\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ + "\3\0\1\12\2\0\1\12\14\0\5\12\1\212\20\12"+ "\17\0\10\12\1\161\1\12\2\0\2\12\1\0\1\12"+ "\1\0\1\12\2\161\1\17\1\0\1\21\1\22\2\0"+ - "\1\12\14\0\1\207\3\12\1\210\1\161\1\12\1\161"+ - "\1\12\1\161\3\12\1\161\1\22\7\12\17\0\12\12"+ - "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ - "\2\0\1\12\14\0\5\12\1\211\20\12\17\0\10\12"+ - "\1\161\1\12\2\0\2\12\1\0\1\12\1\0\1\12"+ - "\2\161\1\17\1\0\1\21\1\22\2\0\1\12\14\0"+ - "\5\12\1\212\1\12\1\161\1\12\1\161\3\12\1\161"+ - "\1\22\7\12\17\0\10\12\1\161\1\12\2\0\2\12"+ - "\1\0\1\12\1\0\1\12\2\161\1\17\1\0\1\21"+ - "\1\22\2\0\1\12\14\0\5\12\1\161\1\12\1\161"+ - "\1\12\1\161\1\213\1\214\1\12\1\161\1\22\7\12"+ - "\17\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ - "\3\0\1\12\2\0\1\12\14\0\1\215\25\12\17\0"+ - "\12\12\2\0\2\12\1\0\1\12\1\0\3\12\3\0"+ - "\1\12\2\0\1\12\14\0\5\12\1\216\20\12\17\0"+ - "\12\12\2\0\2\12\1\0\1\12\1\0\3\12\3\0"+ - "\1\12\2\0\1\12\14\0\1\12\1\217\1\12\1\220"+ - "\12\12\1\221\3\12\1\222\3\12\17\0\10\12\1\174"+ - "\1\12\2\0\2\12\1\0\1\12\1\0\1\12\2\174"+ - "\1\175\1\0\1\176\1\12\2\0\1\12\14\0\5\12"+ - "\1\223\1\12\1\174\1\12\1\174\1\12\1\224\1\225"+ - "\1\174\10\12\17\0\12\12\2\0\2\12\1\0\1\12"+ - "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\1\226"+ + "\1\12\14\0\5\12\1\213\1\12\1\161\1\12\1\161"+ + "\3\12\1\161\1\22\7\12\17\0\10\12\1\161\1\12"+ + "\2\0\2\12\1\0\1\12\1\0\1\12\2\161\1\17"+ + "\1\0\1\21\1\22\2\0\1\12\14\0\5\12\1\161"+ + "\1\12\1\161\1\12\1\161\1\214\1\215\1\12\1\161"+ + "\1\22\7\12\17\0\12\12\2\0\2\12\1\0\1\12"+ + "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\1\216"+ "\25\12\17\0\12\12\2\0\2\12\1\0\1\12\1\0"+ - "\3\12\3\0\1\12\2\0\1\12\14\0\14\12\1\227"+ - "\11\12\17\0\12\12\2\0\2\12\1\0\1\12\1\0"+ - "\3\12\3\0\1\12\2\0\1\12\14\0\12\12\1\230"+ - "\13\12\17\0\12\12\2\0\2\12\1\0\1\12\1\0"+ - "\3\12\3\0\1\12\2\0\1\12\14\0\25\12\1\231"+ - "\54\0\1\232\113\0\1\233\40\0\1\234\52\0\1\235"+ - "\113\0\1\236\42\0\1\237\50\0\1\240\113\0\1\241"+ - "\113\0\1\242\113\0\1\243\113\0\1\244\47\0\1\245"+ - "\43\0\1\246\47\0\1\247\1\250\15\0\1\251\11\0"+ - "\2\251\1\101\1\0\1\102\25\0\1\251\1\0\1\251"+ - "\1\0\1\251\3\0\1\251\26\0\14\100\1\0\22\100"+ - "\1\0\54\100\14\252\1\0\10\252\1\253\1\254\10\252"+ - "\1\255\54\252\14\256\1\0\11\256\1\257\1\260\7\256"+ - "\1\255\54\256\1\0\10\12\1\261\1\12\2\0\2\12"+ - "\1\0\1\12\1\0\1\12\2\261\1\105\1\0\1\106"+ - "\1\22\2\0\1\12\14\0\5\12\1\261\1\12\1\261"+ - "\1\12\1\261\3\12\1\261\1\22\7\12\16\0\14\262"+ - "\1\0\10\262\1\263\1\264\10\262\1\0\54\262\14\265"+ - "\1\0\11\265\1\266\1\267\7\265\1\0\54\265\13\0"+ - "\1\270\20\0\1\271\2\0\1\272\55\0\10\12\1\261"+ - "\1\12\2\0\2\12\1\0\1\12\1\0\1\12\2\261"+ - "\1\105\1\0\1\106\1\22\2\0\1\12\14\0\1\207"+ - "\3\12\1\210\1\261\1\12\1\261\1\12\1\261\3\12"+ - "\1\261\1\22\7\12\17\0\10\12\1\261\1\12\2\0"+ - "\2\12\1\0\1\12\1\0\1\12\2\261\1\105\1\0"+ - "\1\106\1\22\2\0\1\12\14\0\5\12\1\273\1\12"+ - "\1\261\1\12\1\261\3\12\1\261\1\22\7\12\17\0"+ - "\10\12\1\261\1\12\2\0\2\12\1\0\1\12\1\0"+ - "\1\12\2\261\1\105\1\0\1\106\1\22\2\0\1\12"+ - "\14\0\5\12\1\261\1\12\1\261\1\12\1\261\1\213"+ - "\1\214\1\12\1\261\1\22\7\12\16\0\14\113\1\0"+ - "\10\113\1\0\1\274\1\0\1\113\1\275\5\113\1\0"+ - "\54\113\25\0\1\276\66\0\31\113\2\0\1\277\60\113"+ - "\27\0\1\300\115\0\1\113\63\0\10\12\1\301\1\12"+ - "\2\0\2\12\1\0\1\12\1\0\1\12\2\301\1\122"+ - "\1\0\1\123\1\124\2\0\1\12\14\0\5\12\1\301"+ - "\1\12\1\301\1\12\1\301\3\12\1\301\1\124\7\12"+ - "\16\0\14\302\1\0\10\302\1\303\1\304\10\302\1\0"+ - "\54\302\14\305\1\0\11\305\1\306\1\307\7\305\1\0"+ - "\54\305\1\0\10\12\1\310\1\12\2\0\2\12\1\0"+ - "\1\12\1\0\1\12\2\310\1\311\1\0\1\312\1\12"+ - "\2\0\1\12\14\0\5\12\1\310\1\12\1\310\1\12"+ - "\1\310\3\12\1\310\10\12\16\0\14\313\1\0\10\313"+ - "\1\0\1\313\1\0\2\313\1\0\1\313\1\0\1\313"+ - "\1\177\1\0\4\313\2\0\46\313\1\0\10\12\1\301"+ - "\1\12\2\0\2\12\1\0\1\12\1\0\1\12\2\301"+ - "\1\122\1\0\1\123\1\124\2\0\1\12\14\0\1\207"+ - "\3\12\1\210\1\301\1\12\1\301\1\12\1\301\3\12"+ - "\1\301\1\124\7\12\17\0\10\12\1\301\1\12\2\0"+ - "\2\12\1\0\1\12\1\0\1\12\2\301\1\122\1\0"+ - "\1\123\1\124\2\0\1\12\14\0\5\12\1\314\1\12"+ - "\1\301\1\12\1\301\3\12\1\301\1\124\7\12\17\0"+ - "\10\12\1\301\1\12\2\0\2\12\1\0\1\12\1\0"+ - "\1\12\2\301\1\122\1\0\1\123\1\124\2\0\1\12"+ - "\14\0\5\12\1\301\1\12\1\301\1\12\1\301\1\213"+ - "\1\214\1\12\1\301\1\124\7\12\17\0\10\12\1\310"+ - "\1\12\2\0\2\12\1\0\1\12\1\0\1\12\2\310"+ - "\1\311\1\0\1\312\1\12\2\0\1\12\14\0\5\12"+ - "\1\315\1\12\1\310\1\12\1\310\1\12\1\224\1\225"+ - "\1\310\10\12\16\0\14\142\1\0\10\142\1\0\1\316"+ - "\1\0\1\142\2\0\4\142\1\0\105\142\2\0\1\317"+ - "\60\142\1\0\1\146\1\147\1\146\1\0\1\146\1\0"+ - "\1\151\2\0\1\154\4\0\1\155\1\156\1\0\1\157"+ - "\31\0\1\156\5\0\1\154\32\0\3\147\1\0\1\147"+ - "\1\0\1\320\7\0\1\155\1\156\1\0\1\157\31\0"+ - "\1\156\40\0\5\321\1\0\1\322\1\0\1\321\6\0"+ - "\1\321\2\0\1\321\4\0\1\321\17\0\1\321\1\0"+ - "\1\321\1\0\1\321\2\0\1\321\1\0\1\321\4\0"+ - "\1\321\26\0\1\146\1\147\1\146\1\0\1\146\107\0"+ - "\1\323\1\0\1\323\1\0\1\323\1\0\1\324\105\0"+ - "\1\325\3\0\1\325\1\0\1\326\105\0\3\162\1\0"+ - "\1\162\12\0\1\156\1\0\1\157\31\0\1\156\40\0"+ - "\3\327\1\0\1\327\13\0\1\330\54\0\1\330\16\0"+ - "\3\11\1\0\1\11\107\0\10\12\1\331\1\12\2\0"+ - "\2\12\1\0\1\12\1\0\1\12\2\331\1\17\1\0"+ - "\1\21\1\22\2\0\1\12\14\0\5\12\1\331\1\12"+ - "\1\331\1\12\1\331\3\12\1\331\1\22\7\12\17\0"+ - "\3\162\1\0\1\162\1\0\1\332\10\0\1\156\1\0"+ - "\1\157\31\0\1\156\37\0\14\165\1\0\10\165\1\333"+ - "\1\167\10\165\1\170\54\165\25\0\1\334\1\335\5\0"+ - "\1\336\2\0\1\170\5\0\1\336\1\0\1\170\44\0"+ - "\114\165\14\171\1\0\11\171\1\172\1\333\7\171\1\170"+ - "\170\171\26\0\1\335\1\337\4\0\1\336\2\0\1\170"+ - "\5\0\1\336\1\0\1\170\45\0\10\12\1\340\1\12"+ - "\2\0\2\12\1\0\1\12\1\0\1\12\2\340\1\175"+ - "\1\0\1\176\1\12\2\0\1\12\14\0\5\12\1\340"+ - "\1\12\1\340\1\12\1\340\3\12\1\340\10\12\43\0"+ - "\1\341\115\0\1\342\65\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\2\12\1\343\23\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\3\12\1\344\22\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\6\12\1\345\17\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\12\12\1\346\3\12\1\347\7\12\17\0\12\12\2\0"+ - "\2\12\1\0\1\12\1\0\3\12\3\0\1\12\2\0"+ - "\1\12\14\0\3\12\1\350\10\12\1\351\11\12\17\0"+ - "\12\12\2\0\2\12\1\0\1\12\1\0\3\12\3\0"+ - "\1\12\2\0\1\12\14\0\11\12\1\352\14\12\17\0"+ - "\12\12\2\0\2\12\1\0\1\12\1\0\3\12\3\0"+ - "\1\12\2\0\1\12\14\0\14\12\1\353\11\12\17\0"+ - "\12\12\2\0\2\12\1\0\1\12\1\0\3\12\3\0"+ - "\1\12\2\0\1\12\14\0\6\12\1\354\17\12\17\0"+ - "\12\12\2\0\2\12\1\0\1\12\1\0\3\12\3\0"+ - "\1\12\2\0\1\12\14\0\21\12\1\355\4\12\17\0"+ - "\10\12\1\331\1\12\2\0\2\12\1\0\1\12\1\0"+ - "\1\12\2\331\1\17\1\0\1\21\1\22\2\0\1\12"+ - "\14\0\4\12\1\356\1\331\1\12\1\331\1\12\1\331"+ - "\3\12\1\331\1\22\7\12\17\0\12\12\2\0\2\12"+ + "\3\12\3\0\1\12\2\0\1\12\14\0\5\12\1\217"+ + "\20\12\17\0\12\12\2\0\2\12\1\0\1\12\1\0"+ + "\3\12\3\0\1\12\2\0\1\12\14\0\1\12\1\220"+ + "\1\12\1\221\12\12\1\222\3\12\1\223\3\12\17\0"+ + "\10\12\1\174\1\12\2\0\2\12\1\0\1\12\1\0"+ + "\1\12\2\174\1\175\1\0\1\176\1\12\2\0\1\12"+ + "\14\0\5\12\1\224\1\12\1\174\1\12\1\174\1\12"+ + "\1\225\1\226\1\174\10\12\17\0\12\12\2\0\2\12"+ "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ - "\14\0\1\357\25\12\17\0\12\12\2\0\2\12\1\0"+ + "\14\0\1\227\25\12\17\0\12\12\2\0\2\12\1\0"+ "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\1\12\1\360\24\12\17\0\12\12\2\0\2\12\1\0"+ + "\14\12\1\230\11\12\17\0\12\12\2\0\2\12\1\0"+ "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\22\12\1\361\3\12\17\0\12\12\2\0\2\12\1\0"+ + "\12\12\1\231\13\12\17\0\12\12\2\0\2\12\1\0"+ "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\20\12\1\362\5\12\17\0\10\12\1\340\1\12\2\0"+ - "\2\12\1\0\1\12\1\0\1\12\2\340\1\175\1\0"+ - "\1\176\1\12\2\0\1\12\14\0\5\12\1\340\1\12"+ - "\1\340\1\12\1\340\1\12\1\363\1\12\1\340\10\12"+ + "\25\12\1\232\54\0\1\233\113\0\1\234\40\0\1\235"+ + "\52\0\1\236\113\0\1\237\42\0\1\240\50\0\1\241"+ + "\113\0\1\242\113\0\1\243\113\0\1\244\113\0\1\245"+ + "\47\0\1\246\43\0\1\247\47\0\1\250\1\251\15\0"+ + "\1\252\11\0\2\252\1\101\1\0\1\102\25\0\1\252"+ + "\1\0\1\252\1\0\1\252\3\0\1\252\26\0\14\100"+ + "\1\0\22\100\1\0\54\100\14\253\1\0\10\253\1\254"+ + "\1\255\10\253\1\256\54\253\14\257\1\0\11\257\1\260"+ + "\1\261\7\257\1\256\54\257\1\0\10\12\1\262\1\12"+ + "\2\0\2\12\1\0\1\12\1\0\1\12\2\262\1\105"+ + "\1\0\1\106\1\22\2\0\1\12\14\0\5\12\1\262"+ + "\1\12\1\262\1\12\1\262\3\12\1\262\1\22\7\12"+ + "\16\0\14\263\1\0\10\263\1\264\1\265\10\263\1\0"+ + "\54\263\14\266\1\0\11\266\1\267\1\270\7\266\1\0"+ + "\54\266\13\0\1\271\20\0\1\272\1\0\1\201\1\273"+ + "\55\0\10\12\1\262\1\12\2\0\2\12\1\0\1\12"+ + "\1\0\1\12\2\262\1\105\1\0\1\106\1\22\2\0"+ + "\1\12\14\0\1\210\3\12\1\211\1\262\1\12\1\262"+ + "\1\12\1\262\3\12\1\262\1\22\7\12\17\0\10\12"+ + "\1\262\1\12\2\0\2\12\1\0\1\12\1\0\1\12"+ + "\2\262\1\105\1\0\1\106\1\22\2\0\1\12\14\0"+ + "\5\12\1\274\1\12\1\262\1\12\1\262\3\12\1\262"+ + "\1\22\7\12\17\0\10\12\1\262\1\12\2\0\2\12"+ + "\1\0\1\12\1\0\1\12\2\262\1\105\1\0\1\106"+ + "\1\22\2\0\1\12\14\0\5\12\1\262\1\12\1\262"+ + "\1\12\1\262\1\214\1\215\1\12\1\262\1\22\7\12"+ + "\16\0\14\113\1\0\10\113\1\0\1\275\1\0\1\113"+ + "\1\276\5\113\1\0\54\113\25\0\1\277\66\0\31\113"+ + "\2\0\1\300\60\113\27\0\1\301\115\0\1\113\63\0"+ + "\10\12\1\302\1\12\2\0\2\12\1\0\1\12\1\0"+ + "\1\12\2\302\1\122\1\0\1\123\1\124\2\0\1\12"+ + "\14\0\5\12\1\302\1\12\1\302\1\12\1\302\3\12"+ + "\1\302\1\124\7\12\16\0\14\303\1\0\10\303\1\304"+ + "\1\305\10\303\1\0\54\303\14\306\1\0\11\306\1\307"+ + "\1\310\7\306\1\0\54\306\1\0\10\12\1\311\1\12"+ + "\2\0\2\12\1\0\1\12\1\0\1\12\2\311\1\312"+ + "\1\0\1\313\1\12\2\0\1\12\14\0\5\12\1\311"+ + "\1\12\1\311\1\12\1\311\3\12\1\311\10\12\16\0"+ + "\14\314\1\0\10\314\1\0\1\314\1\0\2\314\1\0"+ + "\1\314\1\0\1\314\1\177\1\0\4\314\2\0\46\314"+ + "\1\0\10\12\1\302\1\12\2\0\2\12\1\0\1\12"+ + "\1\0\1\12\2\302\1\122\1\0\1\123\1\124\2\0"+ + "\1\12\14\0\1\210\3\12\1\211\1\302\1\12\1\302"+ + "\1\12\1\302\3\12\1\302\1\124\7\12\17\0\10\12"+ + "\1\302\1\12\2\0\2\12\1\0\1\12\1\0\1\12"+ + "\2\302\1\122\1\0\1\123\1\124\2\0\1\12\14\0"+ + "\5\12\1\315\1\12\1\302\1\12\1\302\3\12\1\302"+ + "\1\124\7\12\17\0\10\12\1\302\1\12\2\0\2\12"+ + "\1\0\1\12\1\0\1\12\2\302\1\122\1\0\1\123"+ + "\1\124\2\0\1\12\14\0\5\12\1\302\1\12\1\302"+ + "\1\12\1\302\1\214\1\215\1\12\1\302\1\124\7\12"+ + "\17\0\10\12\1\311\1\12\2\0\2\12\1\0\1\12"+ + "\1\0\1\12\2\311\1\312\1\0\1\313\1\12\2\0"+ + "\1\12\14\0\5\12\1\316\1\12\1\311\1\12\1\311"+ + "\1\12\1\225\1\226\1\311\10\12\16\0\14\142\1\0"+ + "\10\142\1\0\1\317\1\0\1\142\2\0\4\142\1\0"+ + "\105\142\2\0\1\320\60\142\1\0\1\146\1\147\1\146"+ + "\1\0\1\146\1\0\1\151\2\0\1\154\4\0\1\155"+ + "\1\156\1\0\1\157\31\0\1\156\5\0\1\154\32\0"+ + "\3\147\1\0\1\147\1\0\1\321\7\0\1\155\1\156"+ + "\1\0\1\157\31\0\1\156\40\0\5\322\1\0\1\323"+ + "\1\0\1\322\6\0\1\322\2\0\1\322\4\0\1\322"+ + "\17\0\1\322\1\0\1\322\1\0\1\322\2\0\1\322"+ + "\1\0\1\322\4\0\1\322\26\0\1\146\1\147\1\146"+ + "\1\0\1\146\107\0\1\324\1\0\1\324\1\0\1\324"+ + "\1\0\1\325\105\0\1\326\3\0\1\326\1\0\1\327"+ + "\105\0\3\162\1\0\1\162\12\0\1\156\1\0\1\157"+ + "\31\0\1\156\40\0\3\330\1\0\1\330\13\0\1\331"+ + "\54\0\1\331\16\0\3\11\1\0\1\11\107\0\10\12"+ + "\1\332\1\12\2\0\2\12\1\0\1\12\1\0\1\12"+ + "\2\332\1\17\1\0\1\21\1\22\2\0\1\12\14\0"+ + "\5\12\1\332\1\12\1\332\1\12\1\332\3\12\1\332"+ + "\1\22\7\12\17\0\3\162\1\0\1\162\1\0\1\333"+ + "\10\0\1\156\1\0\1\157\31\0\1\156\37\0\14\165"+ + "\1\0\10\165\1\334\1\167\10\165\1\170\54\165\25\0"+ + "\1\335\1\336\5\0\1\337\2\0\1\170\5\0\1\337"+ + "\1\0\1\170\44\0\114\165\14\171\1\0\11\171\1\172"+ + "\1\334\7\171\1\170\170\171\26\0\1\336\1\340\4\0"+ + "\1\337\2\0\1\170\5\0\1\337\1\0\1\170\45\0"+ + "\10\12\1\341\1\12\2\0\2\12\1\0\1\12\1\0"+ + "\1\12\2\341\1\175\1\0\1\176\1\12\2\0\1\12"+ + "\14\0\5\12\1\341\1\12\1\341\1\12\1\341\3\12"+ + "\1\341\10\12\43\0\1\342\115\0\1\343\65\0\12\12"+ + "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ + "\2\0\1\12\14\0\2\12\1\344\23\12\17\0\12\12"+ + "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ + "\2\0\1\12\14\0\3\12\1\345\22\12\17\0\12\12"+ + "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ + "\2\0\1\12\14\0\6\12\1\346\17\12\17\0\12\12"+ + "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ + "\2\0\1\12\14\0\12\12\1\347\3\12\1\350\7\12"+ "\17\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ - "\3\0\1\12\2\0\1\12\14\0\5\12\1\364\20\12"+ - "\17\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ - "\3\0\1\12\2\0\1\12\14\0\1\12\1\365\24\12"+ - "\17\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ - "\3\0\1\12\2\0\1\12\14\0\3\12\1\366\22\12"+ - "\17\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ - "\3\0\1\12\2\0\1\12\14\0\4\12\1\367\21\12"+ - "\17\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ - "\3\0\1\12\2\0\1\12\14\0\13\12\1\370\12\12"+ - "\17\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ - "\3\0\1\12\2\0\1\12\14\0\14\12\1\371\11\12"+ - "\54\0\1\372\113\0\1\373\113\0\1\374\113\0\1\375"+ - "\66\0\1\376\11\0\2\376\1\101\1\0\1\102\25\0"+ - "\1\376\1\0\1\376\1\0\1\376\3\0\1\376\26\0"+ - "\14\252\1\0\10\252\1\377\1\254\10\252\1\255\54\252"+ - "\25\0\1\u0100\1\u0101\5\0\1\u0102\2\0\1\255\5\0"+ - "\1\u0102\1\0\1\255\44\0\114\252\14\256\1\0\11\256"+ - "\1\257\1\377\7\256\1\255\170\256\26\0\1\u0101\1\u0103"+ - "\4\0\1\u0102\2\0\1\255\5\0\1\u0102\1\0\1\255"+ - "\45\0\10\12\1\u0104\1\12\2\0\2\12\1\0\1\12"+ - "\1\0\1\12\2\u0104\1\105\1\0\1\106\1\22\2\0"+ - "\1\12\14\0\5\12\1\u0104\1\12\1\u0104\1\12\1\u0104"+ - "\3\12\1\u0104\1\22\7\12\16\0\14\262\1\0\10\262"+ - "\1\u0105\1\264\10\262\1\0\54\262\25\0\1\u0106\66\0"+ - "\114\262\14\265\1\0\11\265\1\266\1\u0105\7\265\1\0"+ - "\170\265\27\0\1\u0107\64\0\14\270\1\0\22\270\1\272"+ - "\54\270\1\0\10\12\1\u0104\1\12\2\0\2\12\1\0"+ - "\1\12\1\0\1\12\2\u0104\1\105\1\0\1\106\1\22"+ - "\2\0\1\12\14\0\4\12\1\356\1\u0104\1\12\1\u0104"+ - "\1\12\1\u0104\3\12\1\u0104\1\22\7\12\43\0\1\u0108"+ - "\66\0\14\113\1\0\10\113\1\0\1\274\1\0\1\113"+ - "\1\277\5\113\1\0\54\113\27\0\1\u0108\65\0\10\12"+ - "\1\u0109\1\12\2\0\2\12\1\0\1\12\1\0\1\12"+ - "\2\u0109\1\122\1\0\1\123\1\124\2\0\1\12\14\0"+ - "\5\12\1\u0109\1\12\1\u0109\1\12\1\u0109\3\12\1\u0109"+ - "\1\124\7\12\16\0\14\302\1\0\10\302\1\u010a\1\304"+ - "\10\302\1\0\54\302\25\0\1\u010b\66\0\114\302\14\305"+ - "\1\0\11\305\1\306\1\u010a\7\305\1\0\170\305\27\0"+ - "\1\u010c\65\0\10\12\1\u010d\1\12\2\0\2\12\1\0"+ - "\1\12\1\0\1\12\2\u010d\1\311\1\0\1\312\1\12"+ - "\2\0\1\12\14\0\5\12\1\u010d\1\12\1\u010d\1\12"+ - "\1\u010d\3\12\1\u010d\10\12\43\0\1\u010e\115\0\1\u010f"+ - "\64\0\14\313\1\0\10\313\1\0\1\313\1\0\2\313"+ - "\1\0\1\313\1\0\1\313\2\0\4\313\2\0\46\313"+ - "\1\0\10\12\1\u0109\1\12\2\0\2\12\1\0\1\12"+ - "\1\0\1\12\2\u0109\1\122\1\0\1\123\1\124\2\0"+ - "\1\12\14\0\4\12\1\356\1\u0109\1\12\1\u0109\1\12"+ - "\1\u0109\3\12\1\u0109\1\124\7\12\17\0\10\12\1\u010d"+ - "\1\12\2\0\2\12\1\0\1\12\1\0\1\12\2\u010d"+ - "\1\311\1\0\1\312\1\12\2\0\1\12\14\0\5\12"+ - "\1\u010d\1\12\1\u010d\1\12\1\u010d\1\12\1\363\1\12"+ - "\1\u010d\10\12\16\0\14\142\1\0\10\142\1\0\1\316"+ - "\1\0\1\142\1\u0110\1\0\4\142\1\0\54\142\1\0"+ - "\3\147\1\0\1\147\107\0\5\321\1\0\1\322\1\0"+ - "\1\321\1\154\5\0\1\321\2\0\1\321\4\0\1\321"+ - "\17\0\1\321\1\0\1\321\1\0\1\321\2\0\1\321"+ - "\1\0\1\321\1\154\3\0\1\321\26\0\5\321\3\0"+ - "\1\321\6\0\1\321\2\0\1\321\4\0\1\321\17\0"+ - "\1\321\1\0\1\321\1\0\1\321\2\0\1\321\1\0"+ - "\1\321\4\0\1\321\26\0\1\323\1\0\1\323\1\0"+ - "\1\323\1\0\1\324\2\0\1\154\47\0\1\154\32\0"+ - "\1\323\1\0\1\323\1\0\1\323\107\0\1\325\3\0"+ - "\1\325\1\0\1\326\2\0\1\154\47\0\1\154\32\0"+ - "\1\325\3\0\1\325\107\0\3\327\1\0\1\327\1\0"+ - "\1\330\12\0\1\157\72\0\3\327\1\0\1\327\107\0"+ - "\12\12\2\0\2\12\1\0\1\12\1\0\3\12\1\17"+ - "\1\0\1\21\1\22\2\0\1\12\14\0\16\12\1\22"+ - "\7\12\44\0\1\335\5\0\1\336\2\0\1\170\5\0"+ - "\1\336\1\0\1\170\44\0\25\334\1\u0111\1\u0112\65\334"+ - "\26\337\1\u0113\1\u0114\64\337\1\0\10\12\1\u0115\1\12"+ - "\2\0\2\12\1\0\1\12\1\0\1\12\2\u0115\1\175"+ - "\1\0\1\176\1\12\2\0\1\12\14\0\5\12\1\u0115"+ - "\1\12\1\u0115\1\12\1\u0115\3\12\1\u0115\10\12\43\0"+ - "\1\u0116\115\0\1\u0116\65\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\4\12\1\u0117\21\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\4\12\1\u0118\21\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\16\12\1\u0119\7\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\4\12\1\u011a\21\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\3\12\1\u011b\22\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\15\12\1\u011c\10\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\1\u011d\25\12\17\0\12\12\2\0\2\12\1\0\1\12"+ - "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\3\12"+ - "\1\u011e\22\12\17\0\12\12\2\0\2\12\1\0\1\12"+ + "\3\0\1\12\2\0\1\12\14\0\3\12\1\351\10\12"+ + "\1\352\11\12\17\0\12\12\2\0\2\12\1\0\1\12"+ + "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\11\12"+ + "\1\353\14\12\17\0\12\12\2\0\2\12\1\0\1\12"+ + "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\14\12"+ + "\1\354\11\12\17\0\12\12\2\0\2\12\1\0\1\12"+ "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\6\12"+ - "\1\u011f\17\12\17\0\12\12\2\0\2\12\1\0\1\12"+ + "\1\355\17\12\17\0\12\12\2\0\2\12\1\0\1\12"+ + "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\21\12"+ + "\1\356\4\12\17\0\10\12\1\332\1\12\2\0\2\12"+ + "\1\0\1\12\1\0\1\12\2\332\1\17\1\0\1\21"+ + "\1\22\2\0\1\12\14\0\4\12\1\357\1\332\1\12"+ + "\1\332\1\12\1\332\3\12\1\332\1\22\7\12\17\0"+ + "\12\12\2\0\2\12\1\0\1\12\1\0\3\12\3\0"+ + "\1\12\2\0\1\12\14\0\1\360\25\12\17\0\12\12"+ + "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ + "\2\0\1\12\14\0\1\12\1\361\24\12\17\0\12\12"+ + "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ + "\2\0\1\12\14\0\22\12\1\362\3\12\17\0\12\12"+ + "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ + "\2\0\1\12\14\0\20\12\1\363\5\12\17\0\10\12"+ + "\1\341\1\12\2\0\2\12\1\0\1\12\1\0\1\12"+ + "\2\341\1\175\1\0\1\176\1\12\2\0\1\12\14\0"+ + "\5\12\1\341\1\12\1\341\1\12\1\341\1\12\1\364"+ + "\1\12\1\341\10\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\5\12\1\365\20\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\1\12\1\366\24\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\3\12\1\367\22\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\4\12\1\370\21\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\13\12\1\371\12\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\14\12\1\372\11\12\54\0\1\373\113\0\1\374\113\0"+ + "\1\375\113\0\1\376\66\0\1\377\11\0\2\377\1\101"+ + "\1\0\1\102\25\0\1\377\1\0\1\377\1\0\1\377"+ + "\3\0\1\377\26\0\14\253\1\0\10\253\1\u0100\1\255"+ + "\10\253\1\256\54\253\25\0\1\u0101\1\u0102\5\0\1\u0103"+ + "\2\0\1\256\5\0\1\u0103\1\0\1\256\44\0\114\253"+ + "\14\257\1\0\11\257\1\260\1\u0100\7\257\1\256\170\257"+ + "\26\0\1\u0102\1\u0104\4\0\1\u0103\2\0\1\256\5\0"+ + "\1\u0103\1\0\1\256\45\0\10\12\1\u0105\1\12\2\0"+ + "\2\12\1\0\1\12\1\0\1\12\2\u0105\1\105\1\0"+ + "\1\106\1\22\2\0\1\12\14\0\5\12\1\u0105\1\12"+ + "\1\u0105\1\12\1\u0105\3\12\1\u0105\1\22\7\12\16\0"+ + "\14\263\1\0\10\263\1\u0106\1\265\10\263\1\0\54\263"+ + "\25\0\1\u0107\66\0\114\263\14\266\1\0\11\266\1\267"+ + "\1\u0106\7\266\1\0\170\266\27\0\1\u0108\64\0\14\271"+ + "\1\0\22\271\1\273\54\271\13\0\1\271\20\0\1\272"+ + "\2\0\1\273\55\0\10\12\1\u0105\1\12\2\0\2\12"+ + "\1\0\1\12\1\0\1\12\2\u0105\1\105\1\0\1\106"+ + "\1\22\2\0\1\12\14\0\4\12\1\357\1\u0105\1\12"+ + "\1\u0105\1\12\1\u0105\3\12\1\u0105\1\22\7\12\43\0"+ + "\1\u0109\66\0\14\113\1\0\10\113\1\0\1\275\1\0"+ + "\1\113\1\300\5\113\1\0\54\113\27\0\1\u0109\65\0"+ + "\10\12\1\u010a\1\12\2\0\2\12\1\0\1\12\1\0"+ + "\1\12\2\u010a\1\122\1\0\1\123\1\124\2\0\1\12"+ + "\14\0\5\12\1\u010a\1\12\1\u010a\1\12\1\u010a\3\12"+ + "\1\u010a\1\124\7\12\16\0\14\303\1\0\10\303\1\u010b"+ + "\1\305\10\303\1\0\54\303\25\0\1\u010c\66\0\114\303"+ + "\14\306\1\0\11\306\1\307\1\u010b\7\306\1\0\170\306"+ + "\27\0\1\u010d\65\0\10\12\1\u010e\1\12\2\0\2\12"+ + "\1\0\1\12\1\0\1\12\2\u010e\1\312\1\0\1\313"+ + "\1\12\2\0\1\12\14\0\5\12\1\u010e\1\12\1\u010e"+ + "\1\12\1\u010e\3\12\1\u010e\10\12\43\0\1\u010f\115\0"+ + "\1\u0110\64\0\14\314\1\0\10\314\1\0\1\314\1\0"+ + "\2\314\1\0\1\314\1\0\1\314\2\0\4\314\2\0"+ + "\46\314\1\0\10\12\1\u010a\1\12\2\0\2\12\1\0"+ + "\1\12\1\0\1\12\2\u010a\1\122\1\0\1\123\1\124"+ + "\2\0\1\12\14\0\4\12\1\357\1\u010a\1\12\1\u010a"+ + "\1\12\1\u010a\3\12\1\u010a\1\124\7\12\17\0\10\12"+ + "\1\u010e\1\12\2\0\2\12\1\0\1\12\1\0\1\12"+ + "\2\u010e\1\312\1\0\1\313\1\12\2\0\1\12\14\0"+ + "\5\12\1\u010e\1\12\1\u010e\1\12\1\u010e\1\12\1\364"+ + "\1\12\1\u010e\10\12\16\0\14\142\1\0\10\142\1\0"+ + "\1\317\1\0\1\142\1\u0111\1\0\4\142\1\0\54\142"+ + "\1\0\3\147\1\0\1\147\107\0\5\322\1\0\1\323"+ + "\1\0\1\322\1\154\5\0\1\322\2\0\1\322\4\0"+ + "\1\322\17\0\1\322\1\0\1\322\1\0\1\322\2\0"+ + "\1\322\1\0\1\322\1\154\3\0\1\322\26\0\5\322"+ + "\3\0\1\322\6\0\1\322\2\0\1\322\4\0\1\322"+ + "\17\0\1\322\1\0\1\322\1\0\1\322\2\0\1\322"+ + "\1\0\1\322\4\0\1\322\26\0\1\324\1\0\1\324"+ + "\1\0\1\324\1\0\1\325\2\0\1\154\47\0\1\154"+ + "\32\0\1\324\1\0\1\324\1\0\1\324\107\0\1\326"+ + "\3\0\1\326\1\0\1\327\2\0\1\154\47\0\1\154"+ + "\32\0\1\326\3\0\1\326\107\0\3\330\1\0\1\330"+ + "\1\0\1\331\12\0\1\157\72\0\3\330\1\0\1\330"+ + "\107\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ + "\1\17\1\0\1\21\1\22\2\0\1\12\14\0\16\12"+ + "\1\22\7\12\44\0\1\336\5\0\1\337\2\0\1\170"+ + "\5\0\1\337\1\0\1\170\44\0\25\335\1\u0112\1\u0113"+ + "\65\335\26\340\1\u0114\1\u0115\64\340\1\0\10\12\1\u0116"+ + "\1\12\2\0\2\12\1\0\1\12\1\0\1\12\2\u0116"+ + "\1\175\1\0\1\176\1\12\2\0\1\12\14\0\5\12"+ + "\1\u0116\1\12\1\u0116\1\12\1\u0116\3\12\1\u0116\10\12"+ + "\43\0\1\u0117\115\0\1\u0117\65\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\4\12\1\u0118\21\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\4\12\1\u0119\21\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\16\12\1\u011a\7\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\4\12\1\u011b\21\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\3\12\1\u011c\22\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\15\12\1\u011d\10\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\1\u011e\25\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\3\12\1\u011f\22\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\6\12\1\u0120\17\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\7\12\1\u0121\16\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\13\12\1\u0122\12\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\22\12\1\u0123\3\12\17\0\12\12\2\0\2\12\1\0"+ + "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ + "\1\u0124\25\12\17\0\12\12\2\0\2\12\1\0\1\12"+ + "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\3\12"+ + "\1\u0125\22\12\17\0\12\12\2\0\2\12\1\0\1\12"+ + "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\12\12"+ + "\1\u0126\13\12\17\0\12\12\2\0\2\12\1\0\1\12"+ "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\7\12"+ - "\1\u0120\16\12\17\0\12\12\2\0\2\12\1\0\1\12"+ - "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\13\12"+ - "\1\u0121\12\12\17\0\12\12\2\0\2\12\1\0\1\12"+ - "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\22\12"+ - "\1\u0122\3\12\17\0\12\12\2\0\2\12\1\0\1\12"+ - "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\1\u0123"+ - "\25\12\17\0\12\12\2\0\2\12\1\0\1\12\1\0"+ - "\3\12\3\0\1\12\2\0\1\12\14\0\3\12\1\u0124"+ - "\22\12\17\0\12\12\2\0\2\12\1\0\1\12\1\0"+ - "\3\12\3\0\1\12\2\0\1\12\14\0\12\12\1\u0125"+ - "\13\12\17\0\12\12\2\0\2\12\1\0\1\12\1\0"+ - "\3\12\3\0\1\12\2\0\1\12\14\0\7\12\1\u0126"+ - "\16\12\17\0\12\12\2\0\2\12\1\0\1\12\1\0"+ - "\3\12\3\0\1\12\2\0\1\12\14\0\12\12\1\u0127"+ - "\13\12\43\0\1\101\1\0\1\102\112\0\1\u0101\5\0"+ - "\1\u0102\2\0\1\255\5\0\1\u0102\1\0\1\255\44\0"+ - "\25\u0100\1\u0128\1\u0129\65\u0100\26\u0103\1\u012a\1\u012b\64\u0103"+ - "\1\0\12\12\2\0\2\12\1\0\1\12\1\0\3\12"+ - "\1\105\1\0\1\106\1\22\2\0\1\12\14\0\16\12"+ - "\1\22\7\12\16\0\25\u0106\1\u012c\1\u012d\65\u0106\26\u0107"+ - "\1\u012e\1\u012f\64\u0107\1\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\1\122\1\0\1\123\1\124\2\0"+ - "\1\12\14\0\16\12\1\124\7\12\16\0\25\u010b\1\u0130"+ - "\1\u0131\65\u010b\26\u010c\1\u0132\1\u0133\64\u010c\1\0\10\12"+ - "\1\u0134\1\12\2\0\2\12\1\0\1\12\1\0\1\12"+ - "\2\u0134\1\311\1\0\1\312\1\12\2\0\1\12\14\0"+ - "\5\12\1\u0134\1\12\1\u0134\1\12\1\u0134\3\12\1\u0134"+ - "\10\12\43\0\1\u0135\115\0\1\u0135\64\0\1\142\12\u0110"+ - "\1\142\1\0\2\u0110\1\142\1\u0110\1\142\3\u0110\1\0"+ - "\1\316\1\0\1\u0110\1\0\1\142\2\u0110\2\142\1\0"+ - "\10\142\26\u0110\16\142\25\334\1\u0136\1\u0137\201\334\142\337"+ - "\1\u0138\1\u0139\64\337\1\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\1\175\1\0\1\176\1\12\2\0"+ - "\1\12\14\0\26\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\5\12\1\u013a\20\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\20\12\1\u013b\5\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\4\12\1\u013c\21\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\5\12\1\u013d\20\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\10\12\1\u013e\15\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\3\12\1\u013f\22\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\14\12\1\u0140\11\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\2\12\1\u0141\23\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\5\12\1\u0142\20\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\12\12\1\u0143\13\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\2\12\1\u0144\23\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\1\u0145\25\12\17\0\12\12\2\0\2\12\1\0\1\12"+ - "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\4\12"+ - "\1\u0146\21\12\16\0\25\u0100\1\u0147\1\u0148\201\u0100\142\u0103"+ - "\1\u0149\1\u014a\64\u0103\25\u0106\1\u014b\1\u012d\201\u0106\142\u0107"+ - "\1\u012e\1\u014c\64\u0107\25\u010b\1\u014d\1\u0131\201\u010b\142\u010c"+ - "\1\u0132\1\u014e\64\u010c\1\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\1\311\1\0\1\312\1\12\2\0"+ - "\1\12\14\0\26\12\16\0\25\334\1\u014f\1\u0137\65\334"+ - "\26\337\1\u0138\1\u014f\64\337\1\0\12\12\2\0\2\12"+ + "\1\u0127\16\12\17\0\12\12\2\0\2\12\1\0\1\12"+ + "\1\0\3\12\3\0\1\12\2\0\1\12\14\0\12\12"+ + "\1\u0128\13\12\43\0\1\101\1\0\1\102\112\0\1\u0102"+ + "\5\0\1\u0103\2\0\1\256\5\0\1\u0103\1\0\1\256"+ + "\44\0\25\u0101\1\u0129\1\u012a\65\u0101\26\u0104\1\u012b\1\u012c"+ + "\64\u0104\1\0\12\12\2\0\2\12\1\0\1\12\1\0"+ + "\3\12\1\105\1\0\1\106\1\22\2\0\1\12\14\0"+ + "\16\12\1\22\7\12\16\0\25\u0107\1\u012d\1\u012e\65\u0107"+ + "\26\u0108\1\u012f\1\u0130\64\u0108\1\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\1\122\1\0\1\123\1\124"+ + "\2\0\1\12\14\0\16\12\1\124\7\12\16\0\25\u010c"+ + "\1\u0131\1\u0132\65\u010c\26\u010d\1\u0133\1\u0134\64\u010d\1\0"+ + "\10\12\1\u0135\1\12\2\0\2\12\1\0\1\12\1\0"+ + "\1\12\2\u0135\1\312\1\0\1\313\1\12\2\0\1\12"+ + "\14\0\5\12\1\u0135\1\12\1\u0135\1\12\1\u0135\3\12"+ + "\1\u0135\10\12\43\0\1\u0136\115\0\1\u0136\64\0\1\142"+ + "\12\u0111\1\142\1\0\2\u0111\1\142\1\u0111\1\142\3\u0111"+ + "\1\0\1\317\1\0\1\u0111\1\0\1\142\2\u0111\2\142"+ + "\1\0\10\142\26\u0111\16\142\25\335\1\u0137\1\u0138\201\335"+ + "\142\340\1\u0139\1\u013a\64\340\1\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\1\175\1\0\1\176\1\12"+ + "\2\0\1\12\14\0\26\12\17\0\12\12\2\0\2\12"+ "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ - "\14\0\6\12\1\u0150\17\12\17\0\12\12\2\0\2\12"+ + "\14\0\5\12\1\u013b\20\12\17\0\12\12\2\0\2\12"+ "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ - "\14\0\6\12\1\u0151\17\12\17\0\12\12\2\0\2\12"+ + "\14\0\20\12\1\u013c\5\12\17\0\12\12\2\0\2\12"+ "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ - "\14\0\1\12\1\u0152\24\12\17\0\12\12\2\0\2\12"+ + "\14\0\4\12\1\u013d\21\12\17\0\12\12\2\0\2\12"+ "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ - "\14\0\1\12\1\u0153\24\12\17\0\12\12\2\0\2\12"+ + "\14\0\5\12\1\u013e\20\12\17\0\12\12\2\0\2\12"+ "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ - "\14\0\1\u0154\25\12\17\0\12\12\2\0\2\12\1\0"+ + "\14\0\10\12\1\u013f\15\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\3\12\1\u0140\22\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\14\12\1\u0141\11\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\2\12\1\u0142\23\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\5\12\1\u0143\20\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\12\12\1\u0144\13\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\2\12\1\u0145\23\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\1\u0146\25\12\17\0\12\12\2\0\2\12\1\0"+ "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\6\12\1\u0155\17\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\12\12\1\u0156\13\12\17\0\12\12\2\0\2\12\1\0"+ - "\1\12\1\0\3\12\3\0\1\12\2\0\1\12\14\0"+ - "\12\12\1\u0157\13\12\16\0\25\u0100\1\u0158\1\u0148\65\u0100"+ - "\26\u0103\1\u0149\1\u0158\64\u0103\25\u0106\1\u0159\1\u012d\65\u0106"+ - "\26\u0107\1\u012e\1\u0159\64\u0107\25\u010b\1\u015a\1\u0131\65\u010b"+ - "\26\u010c\1\u0132\1\u015a\64\u010c\26\0\1\u015b\5\0\1\u015c"+ - "\2\0\1\u015d\5\0\1\u015c\1\0\1\u015d\45\0\12\12"+ - "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ - "\2\0\1\12\14\0\15\12\1\u015e\10\12\17\0\12\12"+ - "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ - "\2\0\1\12\14\0\21\12\1\u015f\4\12\17\0\12\12"+ - "\2\0\2\12\1\0\1\12\1\0\3\12\3\0\1\12"+ - "\2\0\1\12\14\0\4\12\1\u0160\21\12\16\0"; + "\4\12\1\u0147\21\12\16\0\25\u0101\1\u0148\1\u0149\201\u0101"+ + "\142\u0104\1\u014a\1\u014b\64\u0104\25\u0107\1\u014c\1\u012e\201\u0107"+ + "\142\u0108\1\u012f\1\u014d\64\u0108\25\u010c\1\u014e\1\u0132\201\u010c"+ + "\142\u010d\1\u0133\1\u014f\64\u010d\1\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\1\312\1\0\1\313\1\12"+ + "\2\0\1\12\14\0\26\12\16\0\25\335\1\u0150\1\u0138"+ + "\65\335\26\340\1\u0139\1\u0150\64\340\1\0\12\12\2\0"+ + "\2\12\1\0\1\12\1\0\3\12\3\0\1\12\2\0"+ + "\1\12\14\0\6\12\1\u0151\17\12\17\0\12\12\2\0"+ + "\2\12\1\0\1\12\1\0\3\12\3\0\1\12\2\0"+ + "\1\12\14\0\6\12\1\u0152\17\12\17\0\12\12\2\0"+ + "\2\12\1\0\1\12\1\0\3\12\3\0\1\12\2\0"+ + "\1\12\14\0\1\12\1\u0153\24\12\17\0\12\12\2\0"+ + "\2\12\1\0\1\12\1\0\3\12\3\0\1\12\2\0"+ + "\1\12\14\0\1\12\1\u0154\24\12\17\0\12\12\2\0"+ + "\2\12\1\0\1\12\1\0\3\12\3\0\1\12\2\0"+ + "\1\12\14\0\1\u0155\25\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\6\12\1\u0156\17\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\12\12\1\u0157\13\12\17\0\12\12\2\0\2\12"+ + "\1\0\1\12\1\0\3\12\3\0\1\12\2\0\1\12"+ + "\14\0\12\12\1\u0158\13\12\16\0\25\u0101\1\u0159\1\u0149"+ + "\65\u0101\26\u0104\1\u014a\1\u0159\64\u0104\25\u0107\1\u015a\1\u012e"+ + "\65\u0107\26\u0108\1\u012f\1\u015a\64\u0108\25\u010c\1\u015b\1\u0132"+ + "\65\u010c\26\u010d\1\u0133\1\u015b\64\u010d\26\0\1\u015c\5\0"+ + "\1\u015d\2\0\1\u015e\5\0\1\u015d\1\0\1\u015e\45\0"+ + "\12\12\2\0\2\12\1\0\1\12\1\0\3\12\3\0"+ + "\1\12\2\0\1\12\14\0\15\12\1\u015f\10\12\17\0"+ + "\12\12\2\0\2\12\1\0\1\12\1\0\3\12\3\0"+ + "\1\12\2\0\1\12\14\0\21\12\1\u0160\4\12\17\0"+ + "\12\12\2\0\2\12\1\0\1\12\1\0\3\12\3\0"+ + "\1\12\2\0\1\12\14\0\4\12\1\u0161\21\12\16\0"; private static int [] zzUnpackTrans() { - int [] result = new int[18848]; + int [] result = new int[19000]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -741,22 +744,23 @@ class _PythonLexer implements FlexLexerEx { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\6\0\1\11\10\1\1\11\2\1\3\11\2\1\11\11"+ - "\32\1\4\11\4\1\1\11\14\1\1\11\4\1\2\11"+ - "\1\1\6\11\6\1\2\11\1\1\5\0\1\11\1\1"+ - "\1\0\1\11\1\0\2\1\2\11\3\1\1\11\6\1"+ - "\2\11\31\1\2\11\1\1\2\11\1\1\5\11\1\1"+ - "\2\11\1\1\1\0\3\1\1\11\12\1\2\0\1\11"+ - "\1\1\2\0\20\1\1\0\1\1\1\0\1\1\1\0"+ + "\6\0\1\11\10\1\1\11\2\1\3\11\2\1\5\11"+ + "\1\1\3\11\32\1\4\11\4\1\1\11\14\1\1\11"+ + "\4\1\2\11\1\1\5\11\7\1\2\11\1\1\5\0"+ + "\1\11\1\1\1\0\1\11\1\0\2\1\2\11\3\1"+ + "\1\11\6\1\3\11\31\1\2\11\1\1\2\11\1\1"+ + "\5\11\1\1\2\11\1\1\1\0\3\1\1\11\12\1"+ + "\2\0\1\11\1\1\2\0\20\1\1\0\1\1\1\0"+ "\1\1\1\0\1\1\1\0\1\1\1\0\1\1\1\0"+ - "\2\1\1\11\1\0\2\1\2\0\27\1\4\11\1\0"+ - "\2\1\1\11\1\0\2\1\1\11\2\1\1\11\1\1"+ - "\1\11\3\1\2\0\1\1\1\0\2\1\1\0\1\1"+ - "\1\11\21\1\1\0\2\1\11\0\1\1\1\11\4\0"+ - "\15\1\10\0\12\1\3\11\1\0\1\11\3\1"; + "\1\1\1\0\2\1\1\11\1\0\2\1\2\0\27\1"+ + "\4\11\1\0\2\1\1\11\1\0\2\1\1\11\2\1"+ + "\1\11\1\1\1\11\3\1\2\0\1\1\1\0\2\1"+ + "\1\0\1\1\1\11\21\1\1\0\2\1\11\0\1\1"+ + "\1\11\4\0\15\1\10\0\12\1\3\11\1\0\1\11"+ + "\3\1"; private static int [] zzUnpackAttribute() { - int [] result = new int[352]; + int [] result = new int[353]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -812,7 +816,7 @@ class _PythonLexer implements FlexLexerEx { private boolean zzEOFDone; /* user code: */ -final PyLexerFStringHelper fStringHelper = new PyLexerFStringHelper(this); +private final PyLexerFStringHelper fStringHelper = new PyLexerFStringHelper(this); private int getSpaceLength(CharSequence string) { String string1 = string.toString(); @@ -870,7 +874,6 @@ return yylength()-s.length(); zzAtEOF = false; zzAtBOL = true; zzEndRead = end; - fStringHelper.reset(); yybegin(initialState); } @@ -1073,605 +1076,610 @@ return yylength()-s.length(); { return PyTokenTypes.BAD_CHARACTER; } // fall through - case 120: break; + case 121: break; case 2: { return PyTokenTypes.INTEGER_LITERAL; } // fall through - case 121: break; + case 122: break; case 3: { return PyTokenTypes.IDENTIFIER; } // fall through - case 122: break; + case 123: break; case 4: { if (zzCurrentPos == 0) yybegin(PENDING_DOCSTRING); return PyTokenTypes.END_OF_LINE_COMMENT; } // fall through - case 123: break; + case 124: break; case 5: { return PyTokenTypes.DOT; } // fall through - case 124: break; + case 125: break; case 6: { return PyTokenTypes.MINUS; } // fall through - case 125: break; + case 126: break; case 7: { if (zzInput == YYEOF && zzStartRead == 0) return PyTokenTypes.DOCSTRING; else return PyTokenTypes.SINGLE_QUOTED_STRING; } // fall through - case 126: break; + case 127: break; case 8: { return PyTokenTypes.BACKSLASH; } // fall through - case 127: break; + case 128: break; case 9: { return PyTokenTypes.LBRACE; } // fall through - case 128: break; + case 129: break; case 10: { return PyTokenTypes.RBRACE; } // fall through - case 129: break; + case 130: break; case 11: { return PyTokenTypes.SPACE; } // fall through - case 130: break; + case 131: break; case 12: { return PyTokenTypes.EQ; } // fall through - case 131: break; + case 132: break; case 13: { if (zzCurrentPos == 0) yybegin(PENDING_DOCSTRING); return PyTokenTypes.LINE_BREAK; } // fall through - case 132: break; + case 133: break; case 14: { return PyTokenTypes.LPAR; } // fall through - case 133: break; + case 134: break; case 15: { return PyTokenTypes.RPAR; } // fall through - case 134: break; + case 135: break; case 16: { return PyTokenTypes.LBRACKET; } // fall through - case 135: break; + case 136: break; case 17: { return PyTokenTypes.RBRACKET; } // fall through - case 136: break; + case 137: break; case 18: { return PyTokenTypes.COLON; } // fall through - case 137: break; + case 138: break; case 19: { return PyTokenTypes.TAB; } // fall through - case 138: break; + case 139: break; case 20: { return PyTokenTypes.FORMFEED; } // fall through - case 139: break; + case 140: break; case 21: { return PyTokenTypes.SEMICOLON; } // fall through - case 140: break; + case 141: break; case 22: { return PyTokenTypes.PLUS; } // fall through - case 141: break; + case 142: break; case 23: { return PyTokenTypes.MULT; } // fall through - case 142: break; + case 143: break; case 24: { return PyTokenTypes.AT; } // fall through - case 143: break; + case 144: break; case 25: { return PyTokenTypes.DIV; } // fall through - case 144: break; + case 145: break; case 26: { return PyTokenTypes.PERC; } // fall through - case 145: break; + case 146: break; case 27: { return PyTokenTypes.AND; } // fall through - case 146: break; + case 147: break; case 28: { return PyTokenTypes.OR; } // fall through - case 147: break; + case 148: break; case 29: { return PyTokenTypes.XOR; } // fall through - case 148: break; + case 149: break; case 30: { return PyTokenTypes.GT; } // fall through - case 149: break; + case 150: break; case 31: { return PyTokenTypes.LT; } // fall through - case 150: break; + case 151: break; case 32: { return PyTokenTypes.TILDE; } // fall through - case 151: break; + case 152: break; case 33: { return PyTokenTypes.COMMA; } // fall through - case 152: break; + case 153: break; case 34: { return PyTokenTypes.TICK; } // fall through - case 153: break; + case 154: break; case 35: { yypushback(1); yybegin(YYINITIAL); } // fall through - case 154: break; + case 155: break; case 36: { return PyTokenTypes.END_OF_LINE_COMMENT; } // fall through - case 155: break; + case 156: break; case 37: { if (zzInput == YYEOF) return PyTokenTypes.DOCSTRING; else yybegin(YYINITIAL); return PyTokenTypes.SINGLE_QUOTED_STRING; } // fall through - case 156: break; + case 157: break; case 38: { return PyTokenTypes.LINE_BREAK; } // fall through - case 157: break; + case 158: break; case 39: { return PyTokenTypes.SINGLE_QUOTED_STRING; } // fall through - case 158: break; + case 159: break; case 40: { return PyTokenTypes.FSTRING_TEXT; } // fall through - case 159: break; + case 160: break; case 41: { return fStringHelper.handleFStringEnd(); } // fall through - case 160: break; + case 161: break; case 42: { return fStringHelper.handleFragmentStart(); } // fall through - case 161: break; + case 162: break; case 43: { return fStringHelper.handleLineBreakInLiteralText(); } // fall through - case 162: break; + case 163: break; case 44: { return fStringHelper.handleStringLiteral(PyTokenTypes.SINGLE_QUOTED_STRING); } // fall through - case 163: break; + case 164: break; case 45: { return fStringHelper.handleLeftBracketInFragment(PyTokenTypes.LBRACE); } // fall through - case 164: break; + case 165: break; case 46: { return fStringHelper.handleRightBracketInFragment(PyTokenTypes.RBRACE); } // fall through - case 165: break; + case 166: break; case 47: { return PyTokenTypes.FSTRING_FRAGMENT_TYPE_CONVERSION; } // fall through - case 166: break; + case 167: break; case 48: { return fStringHelper.handleLineBreakInFragment(); } // fall through - case 167: break; + case 168: break; case 49: { return fStringHelper.handleLeftBracketInFragment(PyTokenTypes.LPAR); } // fall through - case 168: break; + case 169: break; case 50: { return fStringHelper.handleRightBracketInFragment(PyTokenTypes.RPAR); } // fall through - case 169: break; + case 170: break; case 51: { return fStringHelper.handleLeftBracketInFragment(PyTokenTypes.LBRACKET); } // fall through - case 170: break; + case 171: break; case 52: { return fStringHelper.handleRightBracketInFragment(PyTokenTypes.RBRACKET); } // fall through - case 171: break; + case 172: break; case 53: { return fStringHelper.handleColonInFragment(); } // fall through - case 172: break; + case 173: break; case 54: { return fStringHelper.handleFragmentEnd(); } // fall through - case 173: break; + case 174: break; case 55: { return PyTokenTypes.FLOAT_LITERAL; } // fall through - case 174: break; + case 175: break; case 56: { return PyTokenTypes.IMAGINARY_LITERAL; } // fall through - case 175: break; + case 176: break; case 57: { return PyTokenTypes.MINUSEQ; } // fall through - case 176: break; + case 177: break; case 58: { return PyTokenTypes.RARROW; } // fall through - case 177: break; + case 178: break; case 59: { yypushback(getSpaceLength(yytext())); if (zzCurrentPos != 0) return PyTokenTypes.SINGLE_QUOTED_STRING; return PyTokenTypes.DOCSTRING; } // fall through - case 178: break; + case 179: break; case 60: { return fStringHelper.handleFStringStart(); } // fall through - case 179: break; + case 180: break; case 61: { return PyTokenTypes.NE; } // fall through - case 180: break; + case 181: break; case 62: { return PyTokenTypes.EQEQ; } // fall through - case 181: break; - case 63: - { return PyTokenTypes.OR_KEYWORD; - } - // fall through case 182: break; - case 64: - { return PyTokenTypes.IN_KEYWORD; + case 63: + { return PyTokenTypes.COLONEQ; } // fall through case 183: break; - case 65: - { return PyTokenTypes.IS_KEYWORD; + case 64: + { return PyTokenTypes.OR_KEYWORD; } // fall through case 184: break; - case 66: - { return PyTokenTypes.IF_KEYWORD; + case 65: + { return PyTokenTypes.IN_KEYWORD; } // fall through case 185: break; - case 67: - { return PyTokenTypes.PLUSEQ; + case 66: + { return PyTokenTypes.IS_KEYWORD; } // fall through case 186: break; - case 68: - { return PyTokenTypes.MULTEQ; + case 67: + { return PyTokenTypes.IF_KEYWORD; } // fall through case 187: break; - case 69: - { return PyTokenTypes.EXP; + case 68: + { return PyTokenTypes.PLUSEQ; } // fall through case 188: break; - case 70: - { return PyTokenTypes.ATEQ; + case 69: + { return PyTokenTypes.MULTEQ; } // fall through case 189: break; - case 71: - { return PyTokenTypes.DIVEQ; + case 70: + { return PyTokenTypes.EXP; } // fall through case 190: break; - case 72: - { return PyTokenTypes.FLOORDIV; + case 71: + { return PyTokenTypes.ATEQ; } // fall through case 191: break; - case 73: - { return PyTokenTypes.PERCEQ; + case 72: + { return PyTokenTypes.DIVEQ; } // fall through case 192: break; - case 74: - { return PyTokenTypes.ANDEQ; + case 73: + { return PyTokenTypes.FLOORDIV; } // fall through case 193: break; - case 75: - { return PyTokenTypes.OREQ; + case 74: + { return PyTokenTypes.PERCEQ; } // fall through case 194: break; - case 76: - { return PyTokenTypes.XOREQ; + case 75: + { return PyTokenTypes.ANDEQ; } // fall through case 195: break; - case 77: - { return PyTokenTypes.GE; + case 76: + { return PyTokenTypes.OREQ; } // fall through case 196: break; - case 78: - { return PyTokenTypes.GTGT; + case 77: + { return PyTokenTypes.XOREQ; } // fall through case 197: break; - case 79: - { return PyTokenTypes.LE; + case 78: + { return PyTokenTypes.GE; } // fall through case 198: break; - case 80: - { return PyTokenTypes.NE_OLD; + case 79: + { return PyTokenTypes.GTGT; } // fall through case 199: break; - case 81: - { return PyTokenTypes.LTLT; + case 80: + { return PyTokenTypes.LE; } // fall through case 200: break; - case 82: - { yypushback(getSpaceLength(yytext())); yybegin(YYINITIAL); return PyTokenTypes.DOCSTRING; + case 81: + { return PyTokenTypes.NE_OLD; } // fall through case 201: break; - case 83: - { yypushback(yylength()-1); yybegin(PENDING_DOCSTRING); return PyTokenTypes.COLON; + case 82: + { return PyTokenTypes.LTLT; } // fall through case 202: break; - case 84: - { return fStringHelper.handleFStringStartInFragment(); + case 83: + { yypushback(getSpaceLength(yytext())); yybegin(YYINITIAL); return PyTokenTypes.DOCSTRING; } // fall through case 203: break; + case 84: + { yypushback(yylength()-1); yybegin(PENDING_DOCSTRING); return PyTokenTypes.COLON; + } + // fall through + case 204: break; case 85: + { return fStringHelper.handleFStringStartInFragment(); + } + // fall through + case 205: break; + case 86: { if (zzInput == YYEOF && zzStartRead == 0) return PyTokenTypes.DOCSTRING; else return PyTokenTypes.TRIPLE_QUOTED_STRING; } // fall through - case 204: break; - case 86: + case 206: break; + case 87: { yypushback(getSpaceLength(yytext())); if (zzCurrentPos != 0) return PyTokenTypes.SINGLE_QUOTED_STRING; yybegin(PENDING_DOCSTRING); return PyTokenTypes.DOCSTRING; } // fall through - case 205: break; - case 87: + case 207: break; + case 88: { return PyTokenTypes.AND_KEYWORD; } // fall through - case 206: break; - case 88: + case 208: break; + case 89: { return PyTokenTypes.NOT_KEYWORD; } // fall through - case 207: break; - case 89: + case 209: break; + case 90: { return PyTokenTypes.DEL_KEYWORD; } // fall through - case 208: break; - case 90: + case 210: break; + case 91: { yybegin(IN_DOCSTRING_OWNER); return PyTokenTypes.DEF_KEYWORD; } // fall through - case 209: break; - case 91: + case 211: break; + case 92: { return PyTokenTypes.TRY_KEYWORD; } // fall through - case 210: break; - case 92: + case 212: break; + case 93: { return PyTokenTypes.FOR_KEYWORD; } // fall through - case 211: break; - case 93: + case 213: break; + case 94: { return PyTokenTypes.EXPEQ; } // fall through - case 212: break; - case 94: + case 214: break; + case 95: { return PyTokenTypes.FLOORDIVEQ; } // fall through - case 213: break; - case 95: + case 215: break; + case 96: { return PyTokenTypes.GTGTEQ; } // fall through - case 214: break; - case 96: + case 216: break; + case 97: { return PyTokenTypes.LTLTEQ; } // fall through - case 215: break; - case 97: + case 217: break; + case 98: { if (zzInput == YYEOF) return PyTokenTypes.DOCSTRING; else yybegin(YYINITIAL); return PyTokenTypes.TRIPLE_QUOTED_STRING; } // fall through - case 216: break; - case 98: + case 218: break; + case 99: { yypushback(getSpaceLength(yytext())); return PyTokenTypes.DOCSTRING; } // fall through - case 217: break; - case 99: + case 219: break; + case 100: { return PyTokenTypes.TRIPLE_QUOTED_STRING; } // fall through - case 218: break; - case 100: + case 220: break; + case 101: { return fStringHelper.handleStringLiteral(PyTokenTypes.TRIPLE_QUOTED_STRING); } // fall through - case 219: break; - case 101: + case 221: break; + case 102: { yypushback(getSpaceLength(yytext())); if (zzCurrentPos != 0) return PyTokenTypes.TRIPLE_QUOTED_STRING; yybegin(PENDING_DOCSTRING); return PyTokenTypes.DOCSTRING; } // fall through - case 220: break; - case 102: + case 222: break; + case 103: { return PyTokenTypes.ELSE_KEYWORD; } // fall through - case 221: break; - case 103: + case 223: break; + case 104: { return PyTokenTypes.ELIF_KEYWORD; } // fall through - case 222: break; - case 104: + case 224: break; + case 105: { return PyTokenTypes.FROM_KEYWORD; } // fall through - case 223: break; - case 105: + case 225: break; + case 106: { return PyTokenTypes.PASS_KEYWORD; } // fall through - case 224: break; - case 106: + case 226: break; + case 107: { return PyTokenTypes.RAISE_KEYWORD; } // fall through - case 225: break; - case 107: + case 227: break; + case 108: { return PyTokenTypes.BREAK_KEYWORD; } // fall through - case 226: break; - case 108: + case 228: break; + case 109: { yybegin(IN_DOCSTRING_OWNER); return PyTokenTypes.CLASS_KEYWORD; } // fall through - case 227: break; - case 109: + case 229: break; + case 110: { return PyTokenTypes.YIELD_KEYWORD; } // fall through - case 228: break; - case 110: + case 230: break; + case 111: { return PyTokenTypes.WHILE_KEYWORD; } // fall through - case 229: break; - case 111: + case 231: break; + case 112: { return PyTokenTypes.ASSERT_KEYWORD; } // fall through - case 230: break; - case 112: + case 232: break; + case 113: { return PyTokenTypes.EXCEPT_KEYWORD; } // fall through - case 231: break; - case 113: + case 233: break; + case 114: { return PyTokenTypes.RETURN_KEYWORD; } // fall through - case 232: break; - case 114: + case 234: break; + case 115: { return PyTokenTypes.LAMBDA_KEYWORD; } // fall through - case 233: break; - case 115: + case 235: break; + case 116: { return PyTokenTypes.IMPORT_KEYWORD; } // fall through - case 234: break; - case 116: + case 236: break; + case 117: { return PyTokenTypes.GLOBAL_KEYWORD; } // fall through - case 235: break; - case 117: + case 237: break; + case 118: { yypushback(getSpaceLength(yytext())); if (zzCurrentPos != 0) return PyTokenTypes.TRIPLE_QUOTED_STRING; return PyTokenTypes.DOCSTRING; } // fall through - case 236: break; - case 118: + case 238: break; + case 119: { return PyTokenTypes.FINALLY_KEYWORD; } // fall through - case 237: break; - case 119: + case 239: break; + case 120: { return PyTokenTypes.CONTINUE_KEYWORD; } // fall through - case 238: break; + case 240: break; default: zzScanError(ZZ_NO_MATCH); } diff --git a/python/psi-api/src/com/jetbrains/python/PyTokenTypes.java b/python/psi-api/src/com/jetbrains/python/PyTokenTypes.java index 6235cbe1246d..efb90730772b 100644 --- a/python/psi-api/src/com/jetbrains/python/PyTokenTypes.java +++ b/python/psi-api/src/com/jetbrains/python/PyTokenTypes.java @@ -141,13 +141,14 @@ public class PyTokenTypes { public static final PyElementType GTGTEQ = new PyElementType("GTGTEQ");// >>= public static final PyElementType EXPEQ = new PyElementType("EXPEQ");// **= public static final PyElementType RARROW = new PyElementType("RARROW");// -> + public static final PyElementType COLONEQ = new PyElementType("COLONEQ");// := public static final TokenSet OPERATIONS = TokenSet.create( PLUS, MINUS, MULT, AT, EXP, DIV, FLOORDIV, PERC, LTLT, GTGT, AND, OR, XOR, TILDE, LT, GT, LE, GE, EQEQ, NE, NE_OLD, AT, COLON, TICK, EQ, PLUSEQ, MINUSEQ, MULTEQ, ATEQ, DIVEQ, FLOORDIVEQ, PERCEQ, ANDEQ, OREQ, XOREQ, LTLTEQ, GTGTEQ, - EXPEQ); + EXPEQ, COLONEQ); public static final TokenSet COMPARISON_OPERATIONS = TokenSet.create( LT, GT, EQEQ, GE, LE, NE, NE_OLD, IN_KEYWORD, IS_KEYWORD, NOT_KEYWORD); diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyAssignmentExpression.java b/python/psi-api/src/com/jetbrains/python/psi/PyAssignmentExpression.java new file mode 100644 index 000000000000..f90b031cef82 --- /dev/null +++ b/python/psi-api/src/com/jetbrains/python/psi/PyAssignmentExpression.java @@ -0,0 +1,26 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.jetbrains.python.psi; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Represents assignment expressions introduced in Python 3.8 (PEP 572). + */ +@ApiStatus.NonExtendable +@ApiStatus.AvailableSince("2019.2") +public interface PyAssignmentExpression extends PyExpression { + + /** + * @return LHS of an expression (before :=) + */ + @NotNull + PyTargetExpression getTarget(); + + /** + * @return RHS of an expression (after :=) + */ + @Nullable + PyExpression getAssignedValue(); +} diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyElementVisitor.java b/python/psi-api/src/com/jetbrains/python/psi/PyElementVisitor.java index 6f5ded0351af..67368cca866c 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyElementVisitor.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyElementVisitor.java @@ -304,4 +304,8 @@ public class PyElementVisitor extends PsiElementVisitor { public void visitPySingleStarParameter(PySingleStarParameter node) { visitPyElement(node); } + + public void visitPyAssignmentExpression(PyAssignmentExpression node) { + visitPyExpression(node); + } } diff --git a/python/src/com/jetbrains/python/PyElementTypes.java b/python/src/com/jetbrains/python/PyElementTypes.java index 5a7efa7656ab..94da5e87fabb 100644 --- a/python/src/com/jetbrains/python/PyElementTypes.java +++ b/python/src/com/jetbrains/python/PyElementTypes.java @@ -40,7 +40,7 @@ public interface PyElementTypes extends PyStubElementTypes { PyElementType DEL_STATEMENT = new PyElementType("DEL_STATEMENT", PyDelStatementImpl::new); PyElementType EXEC_STATEMENT = new PyElementType("EXEC_STATEMENT", PyExecStatementImpl::new); PyElementType FOR_STATEMENT = new PyElementType("FOR_STATEMENT", PyForStatementImpl::new); - PyElementType TYPE_DECLARATION_STATEMENT = new PyElementType("TYPE_DECLARATION_STATEMENT", PyTypeDeclarationStatementImpl::new); + PyElementType TYPE_DECLARATION_STATEMENT = new PyElementType("TYPE_DECLARATION_STATEMENT", PyTypeDeclarationStatementImpl::new); PyElementType GLOBAL_STATEMENT = new PyElementType("GLOBAL_STATEMENT", PyGlobalStatementImpl::new); PyElementType IF_STATEMENT = new PyElementType("IF_STATEMENT", PyIfStatementImpl::new); @@ -88,6 +88,7 @@ public interface PyElementTypes extends PyStubElementTypes { PyElementType YIELD_EXPRESSION = new PyElementType("YIELD_EXPRESSION", PyYieldExpressionImpl::new); PyElementType STAR_EXPRESSION = new PyElementType("STAR_EXPRESSION", PyStarExpressionImpl::new); PyElementType DOUBLE_STAR_EXPRESSION = new PyElementType("DOUBLE_STAR_EXPRESSION", PyDoubleStarExpressionImpl::new); + PyElementType ASSIGNMENT_EXPRESSION = new PyElementType("ASSIGNMENT_EXPRESSION", PyAssignmentExpressionImpl::new); PyElementType SET_LITERAL_EXPRESSION = new PyElementType("SET_LITERAL_EXPRESSION", PySetLiteralExpressionImpl::new); PyElementType SET_COMP_EXPRESSION = new PyElementType("SET_COMP_EXPRESSION", PySetCompExpressionImpl::new); diff --git a/python/src/com/jetbrains/python/PythonTokenSetContributor.java b/python/src/com/jetbrains/python/PythonTokenSetContributor.java index 5bdc9b51a7ac..e8ca78799e42 100644 --- a/python/src/com/jetbrains/python/PythonTokenSetContributor.java +++ b/python/src/com/jetbrains/python/PythonTokenSetContributor.java @@ -45,7 +45,8 @@ public class PythonTokenSetContributor extends PythonDialectsTokenSetContributor LAMBDA_EXPRESSION, LIST_COMP_EXPRESSION, DICT_LITERAL_EXPRESSION, KEY_VALUE_EXPRESSION, REPR_EXPRESSION, GENERATOR_EXPRESSION, CONDITIONAL_EXPRESSION, YIELD_EXPRESSION, TARGET_EXPRESSION, NONE_LITERAL_EXPRESSION, BOOL_LITERAL_EXPRESSION, - SET_LITERAL_EXPRESSION, SET_COMP_EXPRESSION, DICT_COMP_EXPRESSION, STAR_EXPRESSION, DOUBLE_STAR_EXPRESSION); + SET_LITERAL_EXPRESSION, SET_COMP_EXPRESSION, DICT_COMP_EXPRESSION, STAR_EXPRESSION, DOUBLE_STAR_EXPRESSION, + ASSIGNMENT_EXPRESSION); } @NotNull diff --git a/python/src/com/jetbrains/python/lexer/Python.flex b/python/src/com/jetbrains/python/lexer/Python.flex index ded1f5223068..23ed630a9994 100644 --- a/python/src/com/jetbrains/python/lexer/Python.flex +++ b/python/src/com/jetbrains/python/lexer/Python.flex @@ -265,6 +265,7 @@ return PyTokenTypes.DOCSTRING; } "`" { return PyTokenTypes.TICK; } "=" { return PyTokenTypes.EQ; } ";" { return PyTokenTypes.SEMICOLON; } +":=" { return PyTokenTypes.COLONEQ; } {FSTRING_START} { return fStringHelper.handleFStringStart(); } diff --git a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java index 4203ba3dc0b7..642b735376bc 100644 --- a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java +++ b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java @@ -21,6 +21,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.jetbrains.python.PyElementTypes; +import com.jetbrains.python.PyStubElementTypes; import com.jetbrains.python.PyTokenTypes; import org.jetbrains.annotations.Nullable; @@ -41,7 +42,7 @@ public class ExpressionParsing extends Parsing { final IElementType firstToken = myBuilder.getTokenType(); if (isIdentifier(myBuilder)) { if (isTargetExpression) { - buildTokenElement(PyElementTypes.TARGET_EXPRESSION, myBuilder); + buildTokenElement(PyStubElementTypes.TARGET_EXPRESSION, myBuilder); } else { buildTokenElement(getReferenceType(), myBuilder); @@ -475,7 +476,7 @@ public class ExpressionParsing extends Parsing { myBuilder.advanceLexer(); checkMatches(PyTokenTypes.IDENTIFIER, message("PARSE.expected.name")); if (isTargetExpression && !recastQualifier && !atAnyOfTokens(PyTokenTypes.DOT, PyTokenTypes.LPAR, PyTokenTypes.LBRACKET)) { - expr.done(PyElementTypes.TARGET_EXPRESSION); + expr.done(PyStubElementTypes.TARGET_EXPRESSION); } else { expr.done(getReferenceType()); @@ -602,12 +603,12 @@ public class ExpressionParsing extends Parsing { while (atToken(PyTokenTypes.COMMA)) { nextToken(); PsiBuilder.Marker sliceItemStart = myBuilder.mark(); - parseTestExpression(false, false); + parseNamedTestExpression(false, false); if (matchToken(PyTokenTypes.COLON)) { inSlice = true; - parseTestExpression(false, false); + parseNamedTestExpression(false, false); if (matchToken(PyTokenTypes.COLON)) { - parseTestExpression(false, false); + parseNamedTestExpression(false, false); } } sliceItemStart.done(PyElementTypes.SLICE_ITEM); @@ -733,7 +734,7 @@ public class ExpressionParsing extends Parsing { protected boolean parseTupleExpression(boolean stopOnIn, boolean isTargetExpression, final boolean oldTest) { PsiBuilder.Marker expr = myBuilder.mark(); - boolean exprParseResult = oldTest ? parseOldTestExpression() : parseTestExpression(stopOnIn, isTargetExpression); + boolean exprParseResult = oldTest ? parseOldTestExpression() : parseNamedTestExpression(stopOnIn, isTargetExpression); if (!exprParseResult) { expr.drop(); return false; @@ -742,7 +743,7 @@ public class ExpressionParsing extends Parsing { while (myBuilder.getTokenType() == PyTokenTypes.COMMA) { myBuilder.advanceLexer(); PsiBuilder.Marker expr2 = myBuilder.mark(); - exprParseResult = oldTest ? parseOldTestExpression() : parseTestExpression(stopOnIn, isTargetExpression); + exprParseResult = oldTest ? parseOldTestExpression() : parseNamedTestExpression(stopOnIn, isTargetExpression); if (!exprParseResult) { expr2.rollbackTo(); break; @@ -758,7 +759,7 @@ public class ExpressionParsing extends Parsing { } public boolean parseSingleExpression(boolean isTargetExpression) { - return parseTestExpression(false, isTargetExpression); + return parseNamedTestExpression(false, isTargetExpression); } public boolean parseOldExpression() { @@ -768,6 +769,40 @@ public class ExpressionParsing extends Parsing { return parseORTestExpression(false, false); } + private boolean parseNamedTestExpression(boolean stopOnIn, boolean isTargetExpression) { + final PsiBuilder.Marker expr = myBuilder.mark(); + + if (isIdentifier(myBuilder) && myBuilder.lookAhead(1) == PyTokenTypes.COLONEQ) { + buildTokenElement(PyStubElementTypes.TARGET_EXPRESSION, myBuilder); + + myBuilder.advanceLexer(); + + if (parseTestExpression(stopOnIn, isTargetExpression)) { + expr.done(PyElementTypes.ASSIGNMENT_EXPRESSION); + return true; + } + else { + expr.drop(); + myBuilder.error(message("PARSE.expected.expression")); + return false; + } + } + else if (parseTestExpression(stopOnIn, isTargetExpression)) { + if (!atToken(PyTokenTypes.COLONEQ)) { + expr.drop(); + return true; + } + else { + expr.error(message("PARSE.expected.identifier")); + return false; + } + } + else { + expr.drop(); + return false; + } + } + private boolean parseTestExpression(boolean stopOnIn, boolean isTargetExpression) { if (myBuilder.getTokenType() == PyTokenTypes.LAMBDA_KEYWORD) { return parseLambdaExpression(false); @@ -796,7 +831,7 @@ public class ExpressionParsing extends Parsing { } else { myBuilder.advanceLexer(); - if (!parseTestExpression(stopOnIn, isTargetExpression)) { + if (!parseNamedTestExpression(stopOnIn, isTargetExpression)) { myBuilder.error(message("PARSE.expected.expression")); } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyAssignmentExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyAssignmentExpressionImpl.java new file mode 100644 index 000000000000..6753bf9af03b --- /dev/null +++ b/python/src/com/jetbrains/python/psi/impl/PyAssignmentExpressionImpl.java @@ -0,0 +1,46 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.jetbrains.python.psi.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.util.ObjectUtils; +import com.jetbrains.python.psi.PyAssignmentExpression; +import com.jetbrains.python.psi.PyElementVisitor; +import com.jetbrains.python.psi.PyExpression; +import com.jetbrains.python.psi.PyTargetExpression; +import com.jetbrains.python.psi.types.PyType; +import com.jetbrains.python.psi.types.TypeEvalContext; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +@ApiStatus.Internal +@ApiStatus.AvailableSince("2019.2") +public class PyAssignmentExpressionImpl extends PyElementImpl implements PyAssignmentExpression { + + public PyAssignmentExpressionImpl(@NotNull ASTNode astNode) { + super(astNode); + } + + @NotNull + @Override + public PyTargetExpression getTarget() { + return notNullChild(ObjectUtils.tryCast(getFirstChild(), PyTargetExpression.class)); + } + + @Nullable + @Override + public PyExpression getAssignedValue() { + return ObjectUtils.tryCast(getLastChild(), PyExpression.class); + } + + @Nullable + @Override + public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) { + return context.getType(getTarget()); + } + + @Override + protected void acceptPyVisitor(PyElementVisitor pyVisitor) { + pyVisitor.visitPyAssignmentExpression(this); + } +} diff --git a/python/src/com/jetbrains/python/validation/AssignTargetAnnotator.java b/python/src/com/jetbrains/python/validation/AssignTargetAnnotator.java index c7a09feb49cf..7b80b5cdea16 100644 --- a/python/src/com/jetbrains/python/validation/AssignTargetAnnotator.java +++ b/python/src/com/jetbrains/python/validation/AssignTargetAnnotator.java @@ -19,6 +19,8 @@ import com.intellij.openapi.vfs.VirtualFile; import com.jetbrains.python.PyNames; import com.jetbrains.python.psi.*; import com.jetbrains.python.sdk.PythonSdkType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import static com.jetbrains.python.PyBundle.message; @@ -35,6 +37,9 @@ public class AssignTargetAnnotator extends PyAnnotator { for (PyExpression expression : node.getRawTargets()) { expression.accept(new ExprVisitor(Operation.Assign)); } + + errorOnUnparenthesizedAssignmentExpression(node.getAssignedValue(), + "at the top level of the right hand side of an assignment statement"); } @Override @@ -74,6 +79,37 @@ public class AssignTargetAnnotator extends PyAnnotator { } } + @Override + public void visitPyExpressionStatement(PyExpressionStatement node) { + errorOnUnparenthesizedAssignmentExpression(node.getExpression(), "at the top level of an expression statement"); + } + + @Override + public void visitPyNamedParameter(PyNamedParameter node) { + errorOnUnparenthesizedAssignmentExpression(node.getDefaultValue(), "at the top level of a function default value"); + } + + @Override + public void visitPyKeywordArgument(PyKeywordArgument node) { + errorOnUnparenthesizedAssignmentExpression(node.getValueExpression(), "for the value of a keyword argument in a call"); + } + + @Override + public void visitPyLambdaExpression(PyLambdaExpression node) { + errorOnUnparenthesizedAssignmentExpression(node.getBody(), "at the top level of a lambda function"); + } + + @Override + public void visitPyAnnotation(PyAnnotation node) { + errorOnUnparenthesizedAssignmentExpression(node.getValue(), "as annotations for arguments, return values and assignments"); + } + + private void errorOnUnparenthesizedAssignmentExpression(@Nullable PyExpression expression, @NotNull String suffix) { + if (expression instanceof PyAssignmentExpression) { + getHolder().createErrorAnnotation(expression, "Unparenthesized assignment expressions are prohibited " + suffix); + } + } + private class ExprVisitor extends PyElementVisitor { private final Operation myOp; private final String DELETING_NONE = message("ANN.deleting.none"); diff --git a/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java b/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java index b6254b2a3a52..0d5fe2c86511 100644 --- a/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java +++ b/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java @@ -702,4 +702,11 @@ public abstract class CompatibilityVisitor extends PyAnnotator { " not support equality signs in f-strings", equalitySignInFStringFragment.getPsi()); } } + + @Override + public void visitPyAssignmentExpression(PyAssignmentExpression node) { + super.visitPyAssignmentExpression(node); + registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON38) && registerForLanguageLevel(level), + " not support assignment expressions", node); + } } diff --git a/python/testData/highlighting/invalidAssignmentExpressions.py b/python/testData/highlighting/invalidAssignmentExpressions.py new file mode 100644 index 000000000000..403617f85532 --- /dev/null +++ b/python/testData/highlighting/invalidAssignmentExpressions.py @@ -0,0 +1,23 @@ +y := f(x) # INVALID +(y := f(x)) # Valid, though not recommended + +y0 = y1 := f(x) # INVALID +y0 = (y1 := f(x)) # Valid, though discouraged + +foo(x = y := f(x)) # INVALID +foo(x=(y := f(x))) # Valid, though probably confusing + +def foo(answer = p := 42): # INVALID + pass +def foo(answer=(p := 42)): # Valid, though not great style + pass + +def foo(answer: p := 42 = 5): # INVALID + pass +def foo(answer: (p := 42) = 5): # Valid, but probably never useful + pass + +(lambda: x := 1) # INVALID +lambda: (x := 1) # Valid, but unlikely to be useful +(x := lambda: 1) # Valid +lambda line: (m := re.match(pattern, line)) and m.group(1) # Valid \ No newline at end of file diff --git a/python/testData/highlighting/unsupportedAssignmentExpressions.py b/python/testData/highlighting/unsupportedAssignmentExpressions.py new file mode 100644 index 000000000000..aa01932ee69d --- /dev/null +++ b/python/testData/highlighting/unsupportedAssignmentExpressions.py @@ -0,0 +1,13 @@ +# Handle a matched regex +if (match := pattern.search(data)) is not None: + pass + +# A loop that can't be trivially rewritten using 2-arg iter() +while chunk := file.read(8192): + pass + +# Reuse a value that's expensive to compute +[y := f(x), y**2, y**3] + +# Share a subexpression between a comprehension filter clause and its output +filtered_data = [y for x in data if (y := f(x)) is not None] \ No newline at end of file diff --git a/python/testData/inspections/PyCompatibilityInspection/assignmentExpressions.py b/python/testData/inspections/PyCompatibilityInspection/assignmentExpressions.py new file mode 100644 index 000000000000..a81156554f14 --- /dev/null +++ b/python/testData/inspections/PyCompatibilityInspection/assignmentExpressions.py @@ -0,0 +1,13 @@ +# Handle a matched regex +if (match := pattern.search(data)) is not None: + pass + +# A loop that can't be trivially rewritten using 2-arg iter() +while chunk := file.read(8192): + pass + +# Reuse a value that's expensive to compute +[y := f(x), y**2, y**3] + +# Share a subexpression between a comprehension filter clause and its output +filtered_data = [y for x in data if (y := f(x)) is not None] \ No newline at end of file diff --git a/python/testData/psi/AssignmentExpressions.py b/python/testData/psi/AssignmentExpressions.py new file mode 100644 index 000000000000..55c767efa144 --- /dev/null +++ b/python/testData/psi/AssignmentExpressions.py @@ -0,0 +1,17 @@ +if a := b: + pass + +while c := d: + pass + +[y := 2, y**2, y**3] + +[y for x in data if (y := f(x))] + +len(lines := []) + +foo(x := 1, cat='2') + +(loc := x, y) # loc will be x, not (x, y) + +(px, py, pz := position) # pz will be position, px and py are references \ No newline at end of file diff --git a/python/testData/psi/AssignmentExpressions.txt b/python/testData/psi/AssignmentExpressions.txt new file mode 100644 index 000000000000..e4a6070da8bd --- /dev/null +++ b/python/testData/psi/AssignmentExpressions.txt @@ -0,0 +1,186 @@ +PyFile:AssignmentExpressions.py + PyIfStatement + PyIfPartIf + PsiElement(Py:IF_KEYWORD)('if') + PsiWhiteSpace(' ') + PyAssignmentExpression + PyTargetExpression: a + PsiElement(Py:IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PyReferenceExpression: b + PsiElement(Py:IDENTIFIER)('b') + PsiElement(Py:COLON)(':') + PsiWhiteSpace('\n ') + PyStatementList + PyPassStatement + PsiElement(Py:PASS_KEYWORD)('pass') + PsiWhiteSpace('\n\n') + PyWhileStatement + PyWhilePart + PsiElement(Py:WHILE_KEYWORD)('while') + PsiWhiteSpace(' ') + PyAssignmentExpression + PyTargetExpression: c + PsiElement(Py:IDENTIFIER)('c') + PsiWhiteSpace(' ') + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PyReferenceExpression: d + PsiElement(Py:IDENTIFIER)('d') + PsiElement(Py:COLON)(':') + PsiWhiteSpace('\n ') + PyStatementList + PyPassStatement + PsiElement(Py:PASS_KEYWORD)('pass') + PsiWhiteSpace('\n\n') + PyExpressionStatement + PyListLiteralExpression + PsiElement(Py:LBRACKET)('[') + PyAssignmentExpression + PyTargetExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PyNumericLiteralExpression + PsiElement(Py:INTEGER_LITERAL)('2') + PsiElement(Py:COMMA)(',') + PsiWhiteSpace(' ') + PyBinaryExpression + PyReferenceExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiElement(Py:EXP)('**') + PyNumericLiteralExpression + PsiElement(Py:INTEGER_LITERAL)('2') + PsiElement(Py:COMMA)(',') + PsiWhiteSpace(' ') + PyBinaryExpression + PyReferenceExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiElement(Py:EXP)('**') + PyNumericLiteralExpression + PsiElement(Py:INTEGER_LITERAL)('3') + PsiElement(Py:RBRACKET)(']') + PsiWhiteSpace('\n\n') + PyExpressionStatement + PyListCompExpression + PsiElement(Py:LBRACKET)('[') + PyReferenceExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(Py:FOR_KEYWORD)('for') + PsiWhiteSpace(' ') + PyTargetExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(Py:IN_KEYWORD)('in') + PsiWhiteSpace(' ') + PyReferenceExpression: data + PsiElement(Py:IDENTIFIER)('data') + PsiWhiteSpace(' ') + PsiElement(Py:IF_KEYWORD)('if') + PsiWhiteSpace(' ') + PyParenthesizedExpression + PsiElement(Py:LPAR)('(') + PyAssignmentExpression + PyTargetExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PyCallExpression: f + PyReferenceExpression: f + PsiElement(Py:IDENTIFIER)('f') + PyArgumentList + PsiElement(Py:LPAR)('(') + PyReferenceExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiElement(Py:RPAR)(')') + PsiElement(Py:RPAR)(')') + PsiElement(Py:RBRACKET)(']') + PsiWhiteSpace('\n\n') + PyExpressionStatement + PyCallExpression: len + PyReferenceExpression: len + PsiElement(Py:IDENTIFIER)('len') + PyArgumentList + PsiElement(Py:LPAR)('(') + PyAssignmentExpression + PyTargetExpression: lines + PsiElement(Py:IDENTIFIER)('lines') + PsiWhiteSpace(' ') + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PyListLiteralExpression + PsiElement(Py:LBRACKET)('[') + PsiElement(Py:RBRACKET)(']') + PsiElement(Py:RPAR)(')') + PsiWhiteSpace('\n\n') + PyExpressionStatement + PyCallExpression: foo + PyReferenceExpression: foo + PsiElement(Py:IDENTIFIER)('foo') + PyArgumentList + PsiElement(Py:LPAR)('(') + PyAssignmentExpression + PyTargetExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PyNumericLiteralExpression + PsiElement(Py:INTEGER_LITERAL)('1') + PsiElement(Py:COMMA)(',') + PsiWhiteSpace(' ') + PyKeywordArgumentImpl: cat + PsiElement(Py:IDENTIFIER)('cat') + PsiElement(Py:EQ)('=') + PyStringLiteralExpression: 2 + PsiElement(Py:SINGLE_QUOTED_STRING)(''2'') + PsiElement(Py:RPAR)(')') + PsiWhiteSpace('\n\n') + PyExpressionStatement + PyParenthesizedExpression + PsiElement(Py:LPAR)('(') + PyTupleExpression + PyAssignmentExpression + PyTargetExpression: loc + PsiElement(Py:IDENTIFIER)('loc') + PsiWhiteSpace(' ') + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PyReferenceExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiElement(Py:COMMA)(',') + PsiWhiteSpace(' ') + PyReferenceExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiElement(Py:RPAR)(')') + PsiWhiteSpace(' ') + PsiComment(Py:END_OF_LINE_COMMENT)('# loc will be x, not (x, y)') + PsiWhiteSpace('\n\n') + PyExpressionStatement + PyParenthesizedExpression + PsiElement(Py:LPAR)('(') + PyTupleExpression + PyReferenceExpression: px + PsiElement(Py:IDENTIFIER)('px') + PsiElement(Py:COMMA)(',') + PsiWhiteSpace(' ') + PyReferenceExpression: py + PsiElement(Py:IDENTIFIER)('py') + PsiElement(Py:COMMA)(',') + PsiWhiteSpace(' ') + PyAssignmentExpression + PyTargetExpression: pz + PsiElement(Py:IDENTIFIER)('pz') + PsiWhiteSpace(' ') + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PyReferenceExpression: position + PsiElement(Py:IDENTIFIER)('position') + PsiElement(Py:RPAR)(')') + PsiWhiteSpace(' ') + PsiComment(Py:END_OF_LINE_COMMENT)('# pz will be position, px and py are references') \ No newline at end of file diff --git a/python/testData/psi/InvalidAssignmentExpressions.py b/python/testData/psi/InvalidAssignmentExpressions.py new file mode 100644 index 000000000000..b7ee955e0e07 --- /dev/null +++ b/python/testData/psi/InvalidAssignmentExpressions.py @@ -0,0 +1,10 @@ +# Parenthesis everywhere because +# unparenthesized assignment expressions are prohibited +# at the top level of an expression statement + +(x := y := z := 0) + +(a[i] := x) +(self.rest := []) + +(p: Optional[int] := None) \ No newline at end of file diff --git a/python/testData/psi/InvalidAssignmentExpressions.txt b/python/testData/psi/InvalidAssignmentExpressions.txt new file mode 100644 index 000000000000..89495593c242 --- /dev/null +++ b/python/testData/psi/InvalidAssignmentExpressions.txt @@ -0,0 +1,81 @@ +PyFile:InvalidAssignmentExpressions.py + PsiComment(Py:END_OF_LINE_COMMENT)('# Parenthesis everywhere because') + PsiWhiteSpace('\n') + PsiComment(Py:END_OF_LINE_COMMENT)('# unparenthesized assignment expressions are prohibited') + PsiWhiteSpace('\n') + PsiComment(Py:END_OF_LINE_COMMENT)('# at the top level of an expression statement') + PsiWhiteSpace('\n\n') + PyExpressionStatement + PyParenthesizedExpression + PsiElement(Py:LPAR)('(') + PyAssignmentExpression + PyTargetExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PyReferenceExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiErrorElement:Unexpected expression syntax + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PsiElement(Py:IDENTIFIER)('z') + PsiWhiteSpace(' ') + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PsiElement(Py:INTEGER_LITERAL)('0') + PsiElement(Py:RPAR)(')') + PsiWhiteSpace('\n\n') + PyExpressionStatement + PyParenthesizedExpression + PsiElement(Py:LPAR)('(') + PsiErrorElement:Identifier expected + PySubscriptionExpression + PyReferenceExpression: a + PsiElement(Py:IDENTIFIER)('a') + PsiElement(Py:LBRACKET)('[') + PyReferenceExpression: i + PsiElement(Py:IDENTIFIER)('i') + PsiElement(Py:RBRACKET)(']') + PsiWhiteSpace(' ') + PsiErrorElement:Unexpected expression syntax + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PsiElement(Py:IDENTIFIER)('x') + PsiElement(Py:RPAR)(')') + PsiWhiteSpace('\n') + PyExpressionStatement + PyParenthesizedExpression + PsiElement(Py:LPAR)('(') + PsiErrorElement:Identifier expected + PyReferenceExpression: rest + PyReferenceExpression: self + PsiElement(Py:IDENTIFIER)('self') + PsiElement(Py:DOT)('.') + PsiElement(Py:IDENTIFIER)('rest') + PsiWhiteSpace(' ') + PsiErrorElement:Unexpected expression syntax + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PsiElement(Py:LBRACKET)('[') + PsiElement(Py:RBRACKET)(']') + PsiElement(Py:RPAR)(')') + PsiWhiteSpace('\n\n') + PyExpressionStatement + PyParenthesizedExpression + PsiElement(Py:LPAR)('(') + PyReferenceExpression: p + PsiElement(Py:IDENTIFIER)('p') + PsiErrorElement:Unexpected expression syntax + PsiElement(Py:COLON)(':') + PsiWhiteSpace(' ') + PsiElement(Py:IDENTIFIER)('Optional') + PsiElement(Py:LBRACKET)('[') + PsiElement(Py:IDENTIFIER)('int') + PsiElement(Py:RBRACKET)(']') + PsiWhiteSpace(' ') + PsiElement(Py:COLONEQ)(':=') + PsiWhiteSpace(' ') + PsiElement(Py:NONE_KEYWORD)('None') + PsiElement(Py:RPAR)(')') \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java b/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java index 5175c4135be1..44ad702fd36f 100644 --- a/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java +++ b/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java @@ -426,6 +426,16 @@ public class PythonHighlightingTest extends PyTestCase { doTest(LanguageLevel.PYTHON37, false, false); } + // PY-33886 + public void testInvalidAssignmentExpressions() { + doTest(LanguageLevel.PYTHON38, false, false); + } + + // PY-33886 + public void testUnsupportedAssignmentExpressions() { + doTest(LanguageLevel.PYTHON37, false, false); + } + @NotNull private static EditorColorsScheme createTemporaryColorScheme() { EditorColorsManager manager = EditorColorsManager.getInstance(); diff --git a/python/testSrc/com/jetbrains/python/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/PythonParsingTest.java index 1b4d6aee04b5..df4b7b2d0bfa 100644 --- a/python/testSrc/com/jetbrains/python/PythonParsingTest.java +++ b/python/testSrc/com/jetbrains/python/PythonParsingTest.java @@ -906,6 +906,16 @@ public class PythonParsingTest extends ParsingTestCase { doTest(LanguageLevel.PYTHON37); } + // PY-33886 + public void testAssignmentExpressions() { + doTest(LanguageLevel.PYTHON38); + } + + // PY-33886 + public void testInvalidAssignmentExpressions() { + doTest(LanguageLevel.PYTHON38); + } + public void doTest() { doTest(LanguageLevel.PYTHON26); } diff --git a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java index 3828507ef1ce..b96fd8367e01 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java @@ -235,6 +235,11 @@ public class PyCompatibilityInspectionTest extends PyInspectionTestCase { ); } + // PY-33886 + public void testAssignmentExpressions() { + doTest(LanguageLevel.PYTHON38); + } + private void doTest(@NotNull LanguageLevel level) { runWithLanguageLevel(level, this::doTest); }