PY-18972 Initial support of f-string literals
authorMikhail Golubev <mikhail.golubev@jetbrains.com>
Tue, 6 Sep 2016 17:57:13 +0000 (20:57 +0300)
committerMikhail Golubev <mikhail.golubev@jetbrains.com>
Fri, 16 Sep 2016 05:16:26 +0000 (08:16 +0300)
Namely, Python lexer, compatibility inspection and unsupported
features annotator are aware of them now.

15 files changed:
python/gen/com/jetbrains/python/lexer/_PythonLexer.java
python/src/com/jetbrains/python/lexer/PyStringLiteralLexer.java
python/src/com/jetbrains/python/lexer/Python.flex
python/src/com/jetbrains/python/psi/impl/PyStringLiteralExpressionImpl.java
python/src/com/jetbrains/python/validation/CompatibilityVisitor.java
python/testData/highlighting/fStringLiterals.py [new file with mode: 0644]
python/testData/inspections/PyCompatibilityInspection/stringLiteralExpression.py
python/testData/intentions/removeLeadingF.py [new file with mode: 0644]
python/testData/intentions/removeLeadingF_after.py [new file with mode: 0644]
python/testData/psi/FStrings.py [new file with mode: 0644]
python/testData/psi/FStrings.txt [new file with mode: 0644]
python/testSrc/com/jetbrains/python/PythonHighlightingTest.java
python/testSrc/com/jetbrains/python/PythonLexerTest.java
python/testSrc/com/jetbrains/python/PythonParsingTest.java
python/testSrc/com/jetbrains/python/intentions/PyIntentionTest.java

index 51143eb991ce59efa8181245894ba626a8244d72..c8b81989dc44e34fb639cf87457642c8f9d75a60 100644 (file)
@@ -117,7 +117,7 @@ class _PythonLexer implements FlexLexer {
   static final char ZZ_CMAP_A[] = zzUnpackCMap(
     "\11\0\1\31\1\33\1\111\1\32\1\14\22\0\1\30\1\76\1\27\1\13\1\0\1\70\1\71\1\25"+
     "\1\100\1\101\1\65\1\63\1\106\1\21\1\17\1\67\1\1\1\5\6\3\2\2\1\107\1\34\1\75"+
-    "\1\64\1\74\1\0\1\66\1\4\1\11\1\23\1\4\1\20\1\4\3\15\1\22\1\15\1\12\2\15\1"+
+    "\1\64\1\74\1\0\1\66\1\4\1\11\1\23\1\4\1\20\1\23\3\15\1\22\1\15\1\12\2\15\1"+
     "\10\2\15\1\24\2\15\1\24\2\15\1\6\2\15\1\102\1\26\1\103\1\73\1\7\1\110\1\35"+
     "\1\44\1\46\1\37\1\41\1\53\1\60\1\62\1\51\1\22\1\45\1\47\1\57\1\36\1\50\1\55"+
     "\1\15\1\42\1\40\1\43\1\52\1\15\1\61\1\54\1\56\1\15\1\104\1\72\1\105\1\77\6"+
@@ -182,27 +182,27 @@ class _PythonLexer implements FlexLexer {
     "\1\16\1\17\1\20\1\21\1\22\1\23\1\24\1\25"+
     "\1\26\1\27\1\30\1\1\1\31\1\32\1\33\1\34"+
     "\1\35\1\36\1\37\1\40\1\41\1\42\2\43\1\44"+
-    "\2\45\1\46\1\3\2\47\3\3\1\41\1\2\5\0"+
+    "\2\45\1\46\1\3\2\47\4\3\1\41\1\2\5\0"+
     "\1\2\1\50\1\0\1\51\1\0\1\3\1\50\1\52"+
     "\1\53\3\7\1\54\3\7\15\3\1\55\1\56\1\57"+
     "\1\60\10\3\1\61\1\62\1\63\1\64\1\65\1\66"+
     "\1\67\1\70\1\71\1\72\1\73\1\74\1\75\1\76"+
     "\1\77\1\100\1\101\1\0\3\45\1\102\3\45\1\3"+
-    "\6\47\1\3\2\0\1\103\1\0\1\2\1\0\1\2"+
+    "\6\47\2\3\2\0\1\103\1\0\1\2\1\0\1\2"+
     "\1\0\1\2\1\0\1\50\1\0\1\3\1\0\1\7"+
     "\1\104\1\105\1\0\1\104\1\106\1\3\1\107\1\110"+
     "\1\111\5\3\1\112\6\3\1\113\5\3\1\114\1\115"+
     "\1\116\1\117\1\0\1\45\1\120\1\121\1\0\1\120"+
-    "\1\3\1\47\2\122\3\0\2\123\1\0\1\3\1\124"+
-    "\1\125\10\3\1\126\1\3\1\127\3\3\3\0\2\121"+
-    "\12\0\2\104\1\0\2\3\1\130\1\3\1\131\1\132"+
-    "\4\3\1\133\1\3\1\134\3\0\2\120\4\0\2\122"+
+    "\1\3\1\47\2\122\1\0\2\123\1\0\1\3\1\124"+
+    "\1\125\10\3\1\126\1\3\1\127\3\3\1\0\2\121"+
+    "\6\0\2\104\1\0\2\3\1\130\1\3\1\131\1\132"+
+    "\4\3\1\133\1\3\1\134\1\0\2\120\2\0\2\122"+
     "\1\0\3\104\1\135\1\136\1\137\1\3\1\140\1\141"+
     "\1\3\1\142\3\120\3\122\1\123\1\0\1\143\2\0"+
     "\1\3\1\144\4\0\2\104\1\145\2\120\2\122";
 
   private static int [] zzUnpackAction() {
-    int [] result = new int[307];
+    int [] result = new int[297];
     int offset = 0;
     offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
     return result;
@@ -236,39 +236,38 @@ class _PythonLexer implements FlexLexer {
     "\0\336\0\336\0\336\0\336\0\336\0\336\0\336\0\336"+
     "\0\336\0\336\0\u0bda\0\u0c24\0\u0c6e\0\u0cb8\0\336\0\u0d02"+
     "\0\u0d4c\0\u0d96\0\u0de0\0\u0e2a\0\u0e74\0\u0ebe\0\u0f08\0\u0f52"+
-    "\0\u0f9c\0\u0fe6\0\u1030\0\u107a\0\336\0\u10c4\0\u110e\0\336"+
-    "\0\u1158\0\u11a2\0\u11ec\0\336\0\336\0\u1236\0\u1280\0\u12ca"+
-    "\0\336\0\u1314\0\u135e\0\u13a8\0\u13f2\0\u143c\0\u1486\0\u14d0"+
+    "\0\u0f9c\0\u0fe6\0\u1030\0\u107a\0\u10c4\0\336\0\u110e\0\u1158"+
+    "\0\336\0\u11a2\0\u11ec\0\u1236\0\336\0\336\0\u1280\0\u12ca"+
+    "\0\u1314\0\336\0\u135e\0\u13a8\0\u13f2\0\u143c\0\u1486\0\u14d0"+
     "\0\u151a\0\u1564\0\u15ae\0\u15f8\0\u1642\0\u168c\0\u16d6\0\u1720"+
-    "\0\u176a\0\u01bc\0\u01bc\0\u01bc\0\u01bc\0\u17b4\0\u17fe\0\u1848"+
-    "\0\u1892\0\u18dc\0\u1926\0\u1970\0\u19ba\0\336\0\336\0\336"+
-    "\0\u1a04\0\336\0\336\0\u1a4e\0\336\0\336\0\336\0\336"+
-    "\0\336\0\u1a98\0\336\0\336\0\u1ae2\0\336\0\u1b2c\0\u1b76"+
-    "\0\u1bc0\0\u1c0a\0\336\0\u1c54\0\u1c9e\0\u1ce8\0\u1d32\0\u1d7c"+
-    "\0\u1dc6\0\u1e10\0\u1e5a\0\u1ea4\0\u1eee\0\u1f38\0\u1f82\0\u0ebe"+
-    "\0\336\0\u1fcc\0\u2016\0\u2060\0\u20aa\0\u20f4\0\u213e\0\u2188"+
-    "\0\u21d2\0\u221c\0\u2266\0\u029a\0\u22b0\0\u22fa\0\336\0\u22b0"+
-    "\0\u2344\0\u01bc\0\u238e\0\u01bc\0\u01bc\0\u01bc\0\u23d8\0\u2422"+
-    "\0\u246c\0\u24b6\0\u2500\0\u01bc\0\u254a\0\u2594\0\u25de\0\u2628"+
-    "\0\u2672\0\u26bc\0\u01bc\0\u2706\0\u2750\0\u279a\0\u27e4\0\u282e"+
-    "\0\336\0\336\0\336\0\336\0\u2878\0\u28c2\0\u290c\0\336"+
-    "\0\u28c2\0\u2956\0\u29a0\0\336\0\u29ea\0\u2a34\0\u2a7e\0\u2ac8"+
+    "\0\u176a\0\u17b4\0\u01bc\0\u01bc\0\u01bc\0\u01bc\0\u17fe\0\u1848"+
+    "\0\u1892\0\u18dc\0\u1926\0\u1970\0\u19ba\0\u1a04\0\336\0\336"+
+    "\0\336\0\u1a4e\0\336\0\336\0\u1a98\0\336\0\336\0\336"+
+    "\0\336\0\336\0\u1ae2\0\336\0\336\0\u1b2c\0\336\0\u1b76"+
+    "\0\u1bc0\0\u1c0a\0\u1c54\0\336\0\u1c9e\0\u1ce8\0\u1d32\0\u1d7c"+
+    "\0\u1dc6\0\u1e10\0\u1e5a\0\u1ea4\0\u1eee\0\u1f38\0\u1f82\0\u1fcc"+
+    "\0\u2016\0\u0f08\0\336\0\u2060\0\u20aa\0\u20f4\0\u213e\0\u2188"+
+    "\0\u21d2\0\u221c\0\u2266\0\u22b0\0\u22fa\0\u029a\0\u2344\0\u238e"+
+    "\0\336\0\u2344\0\u23d8\0\u01bc\0\u2422\0\u01bc\0\u01bc\0\u01bc"+
+    "\0\u246c\0\u24b6\0\u2500\0\u254a\0\u2594\0\u01bc\0\u25de\0\u2628"+
+    "\0\u2672\0\u26bc\0\u2706\0\u2750\0\u01bc\0\u279a\0\u27e4\0\u282e"+
+    "\0\u2878\0\u28c2\0\336\0\336\0\336\0\336\0\u290c\0\u2956"+
+    "\0\u29a0\0\336\0\u2956\0\u29ea\0\u2a34\0\336\0\u2a7e\0\u2ac8"+
     "\0\u2b12\0\u2b5c\0\u2ba6\0\u2bf0\0\u2c3a\0\u01bc\0\u01bc\0\u2c84"+
     "\0\u2cce\0\u2d18\0\u2d62\0\u2dac\0\u2df6\0\u2e40\0\u2e8a\0\u01bc"+
     "\0\u2ed4\0\u01bc\0\u2f1e\0\u2f68\0\u2fb2\0\u2ffc\0\u3046\0\u3090"+
     "\0\u30da\0\u3124\0\u316e\0\u31b8\0\u3202\0\u324c\0\u3296\0\u32e0"+
-    "\0\u332a\0\u3374\0\u33be\0\u3408\0\u3452\0\u349c\0\u34e6\0\u3530"+
-    "\0\u357a\0\u01bc\0\u35c4\0\u01bc\0\u01bc\0\u360e\0\u3658\0\u36a2"+
-    "\0\u36ec\0\u01bc\0\u3736\0\u01bc\0\u3780\0\u37ca\0\u3814\0\u385e"+
-    "\0\u38a8\0\u38f2\0\u1dc6\0\u1eee\0\u393c\0\u3986\0\u39d0\0\u3a1a"+
-    "\0\u3a64\0\u3aae\0\u3af8\0\u01bc\0\u01bc\0\u01bc\0\u3b42\0\u01bc"+
-    "\0\u01bc\0\u3b8c\0\u01bc\0\u28c2\0\u3bd6\0\u3c20\0\336\0\u3c6a"+
-    "\0\u3cb4\0\336\0\u3a64\0\336\0\u3cfe\0\u3d48\0\u3d92\0\u01bc"+
-    "\0\u3ddc\0\u3e26\0\u3e70\0\u3eba\0\u3408\0\u34e6\0\u01bc\0\u3814"+
-    "\0\u38f2\0\u393c\0\u3a1a";
+    "\0\u332a\0\u3374\0\u33be\0\u01bc\0\u3408\0\u01bc\0\u01bc\0\u3452"+
+    "\0\u349c\0\u34e6\0\u3530\0\u01bc\0\u357a\0\u01bc\0\u35c4\0\u360e"+
+    "\0\u3658\0\u36a2\0\u36ec\0\u3736\0\u3780\0\u37ca\0\u3814\0\u385e"+
+    "\0\u38a8\0\u01bc\0\u01bc\0\u01bc\0\u38f2\0\u01bc\0\u01bc\0\u393c"+
+    "\0\u01bc\0\u2956\0\u3986\0\u39d0\0\336\0\u3a1a\0\u3a64\0\336"+
+    "\0\u3814\0\336\0\u3aae\0\u3af8\0\u3b42\0\u01bc\0\u3b8c\0\u3bd6"+
+    "\0\u3c20\0\u3c6a\0\u324c\0\u332a\0\u01bc\0\u35c4\0\u36a2\0\u36ec"+
+    "\0\u37ca";
 
   private static int [] zzUnpackRowMap() {
-    int [] result = new int[307];
+    int [] result = new int[297];
     int offset = 0;
     offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
     return result;
@@ -302,257 +301,264 @@ class _PythonLexer implements FlexLexer {
     "\1\65\1\66\1\67\1\70\1\71\1\4\11\72\1\73"+
     "\1\72\1\74\1\0\6\72\2\73\1\75\1\15\1\76"+
     "\1\17\1\20\1\21\1\77\6\72\1\73\1\72\1\73"+
-    "\1\72\1\73\3\72\1\73\36\72\1\0\1\4\1\5"+
+    "\1\72\1\73\3\72\2\73\35\72\1\0\1\4\1\5"+
     "\2\6\1\7\1\6\3\7\1\100\1\7\1\74\1\4"+
     "\1\7\1\4\1\12\1\7\1\13\1\7\2\100\1\101"+
     "\1\15\1\102\1\17\1\20\1\21\1\77\1\23\1\24"+
     "\1\25\1\26\1\7\1\27\1\103\1\31\1\104\1\7"+
-    "\1\105\1\34\1\35\1\36\1\100\1\37\1\7\1\40"+
+    "\1\105\1\34\1\35\1\36\1\100\1\106\1\7\1\40"+
     "\1\41\1\7\1\42\1\43\1\7\1\44\1\45\1\46"+
     "\1\47\1\50\1\51\1\52\1\53\1\54\1\55\1\56"+
     "\1\57\1\60\1\61\1\62\1\63\1\64\1\65\1\66"+
-    "\1\67\1\106\1\71\1\4\113\0\1\107\1\110\1\107"+
-    "\1\0\1\107\1\111\1\112\1\113\1\114\1\115\4\0"+
-    "\1\116\1\117\1\0\1\120\16\0\1\117\2\0\1\114"+
-    "\2\0\1\115\1\113\3\0\1\111\36\0\3\6\1\0"+
-    "\1\6\1\0\1\121\2\0\1\115\4\0\1\116\1\117"+
-    "\1\0\1\120\16\0\1\117\5\0\1\115\43\0\12\7"+
+    "\1\67\1\107\1\71\1\4\113\0\1\110\1\111\1\110"+
+    "\1\0\1\110\1\112\1\113\1\114\1\115\1\116\4\0"+
+    "\1\117\1\120\1\0\1\121\16\0\1\120\2\0\1\115"+
+    "\2\0\1\116\1\114\3\0\1\112\36\0\3\6\1\0"+
+    "\1\6\1\0\1\122\2\0\1\116\4\0\1\117\1\120"+
+    "\1\0\1\121\16\0\1\120\5\0\1\116\43\0\12\7"+
     "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\26\7"+
-    "\30\0\10\7\1\122\1\7\2\0\2\7\1\0\1\7"+
-    "\1\0\1\7\2\122\1\14\1\0\1\16\5\0\5\7"+
-    "\1\122\1\7\1\122\1\7\1\122\3\7\1\122\10\7"+
-    "\27\0\14\11\1\0\16\11\1\0\56\11\1\0\3\123"+
-    "\1\0\1\123\170\0\1\124\7\0\1\125\15\0\14\126"+
-    "\1\0\10\126\1\127\1\130\4\126\1\131\56\126\14\132"+
-    "\1\0\11\132\1\133\1\134\3\132\1\131\56\132\1\0"+
+    "\30\0\10\7\1\123\1\7\2\0\2\7\1\0\1\7"+
+    "\1\0\1\7\2\123\1\14\1\0\1\16\5\0\5\7"+
+    "\1\123\1\7\1\123\1\7\1\123\3\7\2\123\7\7"+
+    "\27\0\14\11\1\0\16\11\1\0\56\11\1\0\3\124"+
+    "\1\0\1\124\170\0\1\125\7\0\1\126\15\0\14\127"+
+    "\1\0\10\127\1\130\1\131\4\127\1\132\56\127\14\133"+
+    "\1\0\11\133\1\134\1\135\3\133\1\132\56\133\1\0"+
     "\12\7\2\0\2\7\1\0\1\7\1\0\3\7\10\0"+
-    "\1\7\1\135\1\7\1\136\22\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\13\7\1\137"+
+    "\1\7\1\136\1\7\1\137\22\7\30\0\12\7\2\0"+
+    "\2\7\1\0\1\7\1\0\3\7\10\0\13\7\1\140"+
     "\12\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\4\7\1\140\21\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\12\7\1\141"+
-    "\4\7\1\142\6\7\30\0\10\7\1\122\1\7\2\0"+
-    "\2\7\1\0\1\7\1\0\1\7\2\122\1\14\1\0"+
-    "\1\16\5\0\1\143\3\7\1\144\1\122\1\7\1\122"+
-    "\1\7\1\122\3\7\1\122\10\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\5\7\1\145"+
-    "\20\7\30\0\10\7\1\122\1\7\2\0\2\7\1\0"+
-    "\1\7\1\0\1\7\2\122\1\14\1\0\1\16\5\0"+
-    "\5\7\1\146\1\7\1\122\1\7\1\122\3\7\1\122"+
-    "\10\7\30\0\10\7\1\122\1\7\2\0\2\7\1\0"+
-    "\1\7\1\0\1\7\2\122\1\14\1\0\1\16\5\0"+
-    "\5\7\1\122\1\7\1\122\1\7\1\122\1\147\1\150"+
-    "\1\7\1\122\10\7\30\0\12\7\2\0\2\7\1\0"+
-    "\1\7\1\0\3\7\10\0\1\151\25\7\30\0\12\7"+
+    "\3\7\10\0\4\7\1\141\21\7\30\0\12\7\2\0"+
+    "\2\7\1\0\1\7\1\0\3\7\10\0\12\7\1\142"+
+    "\4\7\1\143\6\7\30\0\10\7\1\123\1\7\2\0"+
+    "\2\7\1\0\1\7\1\0\1\7\2\123\1\14\1\0"+
+    "\1\16\5\0\1\144\3\7\1\145\1\123\1\7\1\123"+
+    "\1\7\1\123\3\7\2\123\7\7\30\0\12\7\2\0"+
+    "\2\7\1\0\1\7\1\0\3\7\10\0\5\7\1\146"+
+    "\20\7\30\0\10\7\1\123\1\7\2\0\2\7\1\0"+
+    "\1\7\1\0\1\7\2\123\1\14\1\0\1\16\5\0"+
+    "\5\7\1\147\1\7\1\123\1\7\1\123\3\7\2\123"+
+    "\7\7\30\0\10\7\1\123\1\7\2\0\2\7\1\0"+
+    "\1\7\1\0\1\7\2\123\1\14\1\0\1\16\5\0"+
+    "\5\7\1\123\1\7\1\123\1\7\1\123\1\150\1\151"+
+    "\1\7\2\123\7\7\30\0\12\7\2\0\2\7\1\0"+
+    "\1\7\1\0\3\7\10\0\1\152\25\7\30\0\12\7"+
     "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\5\7"+
-    "\1\152\20\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\1\7\1\153\1\7\1\154\12\7"+
-    "\1\155\3\7\1\156\3\7\30\0\12\7\2\0\2\7"+
-    "\1\0\1\7\1\0\3\7\10\0\5\7\1\157\5\7"+
-    "\1\160\1\161\11\7\30\0\12\7\2\0\2\7\1\0"+
-    "\1\7\1\0\3\7\10\0\1\162\25\7\30\0\12\7"+
-    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\14\7"+
-    "\1\163\11\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\12\7\1\164\13\7\30\0\12\7"+
-    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\25\7"+
-    "\1\165\113\0\1\166\111\0\1\167\111\0\1\170\1\171"+
-    "\110\0\1\172\111\0\1\173\2\0\1\174\106\0\1\175"+
-    "\111\0\1\176\111\0\1\177\111\0\1\200\111\0\1\201"+
-    "\7\0\1\202\101\0\1\203\7\0\1\204\1\205\100\0"+
-    "\1\206\36\0\1\207\11\0\2\207\1\75\1\0\1\76"+
-    "\12\0\1\207\1\0\1\207\1\0\1\207\3\0\1\207"+
-    "\37\0\14\74\1\0\16\74\1\0\56\74\14\210\1\0"+
-    "\10\210\1\211\1\212\4\210\1\213\56\210\14\214\1\0"+
-    "\11\214\1\215\1\216\3\214\1\213\56\214\1\0\10\7"+
-    "\1\217\1\7\2\0\2\7\1\0\1\7\1\0\1\7"+
-    "\2\217\1\101\1\0\1\102\5\0\5\7\1\217\1\7"+
-    "\1\217\1\7\1\217\3\7\1\217\10\7\27\0\14\220"+
-    "\1\0\10\220\1\221\1\222\4\220\1\0\56\220\14\223"+
-    "\1\0\11\223\1\224\1\225\3\223\1\0\56\223\1\0"+
-    "\10\7\1\217\1\7\2\0\2\7\1\0\1\7\1\0"+
-    "\1\7\2\217\1\101\1\0\1\102\5\0\1\143\3\7"+
-    "\1\144\1\217\1\7\1\217\1\7\1\217\3\7\1\217"+
-    "\10\7\30\0\10\7\1\217\1\7\2\0\2\7\1\0"+
-    "\1\7\1\0\1\7\2\217\1\101\1\0\1\102\5\0"+
-    "\5\7\1\226\1\7\1\217\1\7\1\217\3\7\1\217"+
-    "\10\7\30\0\10\7\1\217\1\7\2\0\2\7\1\0"+
-    "\1\7\1\0\1\7\2\217\1\101\1\0\1\102\5\0"+
-    "\5\7\1\217\1\7\1\217\1\7\1\217\1\147\1\150"+
-    "\1\7\1\217\10\7\42\0\1\227\14\0\1\230\2\0"+
-    "\1\231\57\0\1\107\1\110\1\107\1\0\1\107\1\0"+
-    "\1\112\2\0\1\115\4\0\1\116\1\117\1\0\1\120"+
-    "\16\0\1\117\5\0\1\115\43\0\3\110\1\0\1\110"+
-    "\1\0\1\232\7\0\1\116\1\117\1\0\1\120\16\0"+
-    "\1\117\51\0\5\233\1\0\1\234\1\0\1\233\6\0"+
-    "\1\233\2\0\1\233\11\0\1\233\1\0\1\233\1\0"+
-    "\1\233\2\0\1\233\1\0\1\233\4\0\1\233\37\0"+
-    "\1\107\1\110\1\107\1\0\1\107\105\0\1\235\1\0"+
-    "\1\235\1\0\1\235\1\0\1\236\103\0\1\237\3\0"+
-    "\1\237\1\0\1\240\103\0\3\123\1\0\1\123\12\0"+
-    "\1\117\1\0\1\120\16\0\1\117\51\0\3\241\1\0"+
-    "\1\241\13\0\1\242\41\0\1\242\27\0\3\6\1\0"+
-    "\1\6\105\0\10\7\1\243\1\7\2\0\2\7\1\0"+
-    "\1\7\1\0\1\7\2\243\1\14\1\0\1\16\5\0"+
-    "\5\7\1\243\1\7\1\243\1\7\1\243\3\7\1\243"+
-    "\10\7\30\0\3\123\1\0\1\123\1\0\1\244\10\0"+
-    "\1\117\1\0\1\120\16\0\1\117\50\0\14\126\1\0"+
-    "\10\126\1\245\1\130\4\126\1\131\56\126\25\0\1\246"+
-    "\1\247\1\0\2\250\1\0\2\131\55\0\112\126\14\132"+
-    "\1\0\11\132\1\133\1\245\3\132\1\131\170\132\26\0"+
-    "\1\247\1\251\2\250\1\0\2\131\56\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\2\7\1\252"+
-    "\23\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\3\7\1\253\22\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\6\7\1\254"+
-    "\17\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\12\7\1\255\3\7\1\256\7\7\30\0"+
-    "\12\7\2\0\2\7\1\0\1\7\1\0\3\7\10\0"+
-    "\3\7\1\257\10\7\1\260\11\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\11\7\1\261"+
-    "\14\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\14\7\1\262\11\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\6\7\1\263"+
-    "\17\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\21\7\1\264\4\7\30\0\10\7\1\243"+
-    "\1\7\2\0\2\7\1\0\1\7\1\0\1\7\2\243"+
-    "\1\14\1\0\1\16\5\0\4\7\1\265\1\243\1\7"+
-    "\1\243\1\7\1\243\3\7\1\243\10\7\30\0\12\7"+
-    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\1\266"+
+    "\1\153\20\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\1\7\1\154\1\7\1\155\12\7"+
+    "\1\156\3\7\1\157\3\7\30\0\10\7\1\123\1\7"+
+    "\2\0\2\7\1\0\1\7\1\0\1\7\2\123\1\14"+
+    "\1\0\1\16\5\0\5\7\1\160\1\7\1\123\1\7"+
+    "\1\123\1\7\1\161\1\162\2\123\7\7\30\0\12\7"+
+    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\1\163"+
     "\25\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\1\7\1\267\24\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\22\7\1\270"+
-    "\3\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\20\7\1\271\5\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\13\7\1\272"+
-    "\12\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\5\7\1\273\20\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\1\7\1\274"+
-    "\24\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\3\7\1\275\22\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\4\7\1\276"+
-    "\21\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\13\7\1\277\12\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\14\7\1\300"+
-    "\11\7\113\0\1\301\111\0\1\302\111\0\1\303\111\0"+
-    "\1\304\36\0\1\305\11\0\2\305\1\75\1\0\1\76"+
-    "\12\0\1\305\1\0\1\305\1\0\1\305\3\0\1\305"+
-    "\37\0\14\210\1\0\10\210\1\306\1\212\4\210\1\213"+
-    "\56\210\25\0\1\307\1\310\1\0\2\311\1\0\2\213"+
-    "\55\0\112\210\14\214\1\0\11\214\1\215\1\306\3\214"+
-    "\1\213\170\214\26\0\1\310\1\312\2\311\1\0\2\213"+
-    "\56\0\10\7\1\313\1\7\2\0\2\7\1\0\1\7"+
-    "\1\0\1\7\2\313\1\101\1\0\1\102\5\0\5\7"+
-    "\1\313\1\7\1\313\1\7\1\313\3\7\1\313\10\7"+
-    "\27\0\14\220\1\0\10\220\1\314\1\222\4\220\1\0"+
-    "\56\220\25\0\1\315\64\0\112\220\14\223\1\0\11\223"+
-    "\1\224\1\314\3\223\1\0\170\223\27\0\1\316\63\0"+
-    "\10\7\1\313\1\7\2\0\2\7\1\0\1\7\1\0"+
-    "\1\7\2\313\1\101\1\0\1\102\5\0\4\7\1\265"+
-    "\1\313\1\7\1\313\1\7\1\313\3\7\1\313\10\7"+
-    "\27\0\14\227\1\0\16\227\1\231\56\227\1\0\3\110"+
-    "\1\0\1\110\105\0\5\233\1\0\1\234\1\0\1\233"+
-    "\1\115\5\0\1\233\2\0\1\233\11\0\1\233\1\0"+
-    "\1\233\1\0\1\233\2\0\1\233\1\0\1\233\1\115"+
-    "\3\0\1\233\37\0\5\233\3\0\1\233\6\0\1\233"+
-    "\2\0\1\233\11\0\1\233\1\0\1\233\1\0\1\233"+
-    "\2\0\1\233\1\0\1\233\4\0\1\233\37\0\1\235"+
-    "\1\0\1\235\1\0\1\235\1\0\1\236\2\0\1\115"+
-    "\34\0\1\115\43\0\1\235\1\0\1\235\1\0\1\235"+
-    "\105\0\1\237\3\0\1\237\1\0\1\240\2\0\1\115"+
-    "\34\0\1\115\43\0\1\237\3\0\1\237\105\0\3\241"+
-    "\1\0\1\241\1\0\1\242\12\0\1\120\70\0\3\241"+
-    "\1\0\1\241\105\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\1\317\1\0\1\320\5\0\26\7\55\0"+
-    "\1\247\1\0\2\250\1\0\2\131\55\0\25\246\1\321"+
-    "\1\322\63\246\26\251\1\323\1\324\62\251\1\0\12\7"+
-    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\4\7"+
-    "\1\325\21\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\4\7\1\326\21\7\30\0\12\7"+
-    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\16\7"+
-    "\1\327\7\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\4\7\1\330\21\7\30\0\12\7"+
+    "\3\7\10\0\14\7\1\164\11\7\30\0\12\7\2\0"+
+    "\2\7\1\0\1\7\1\0\3\7\10\0\12\7\1\165"+
+    "\13\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
+    "\3\7\10\0\25\7\1\166\113\0\1\167\111\0\1\170"+
+    "\111\0\1\171\1\172\110\0\1\173\111\0\1\174\2\0"+
+    "\1\175\106\0\1\176\111\0\1\177\111\0\1\200\111\0"+
+    "\1\201\111\0\1\202\7\0\1\203\101\0\1\204\7\0"+
+    "\1\205\1\206\100\0\1\207\36\0\1\210\11\0\2\210"+
+    "\1\75\1\0\1\76\12\0\1\210\1\0\1\210\1\0"+
+    "\1\210\3\0\2\210\36\0\14\74\1\0\16\74\1\0"+
+    "\56\74\14\211\1\0\10\211\1\212\1\213\4\211\1\214"+
+    "\56\211\14\215\1\0\11\215\1\216\1\217\3\215\1\214"+
+    "\56\215\1\0\10\7\1\220\1\7\2\0\2\7\1\0"+
+    "\1\7\1\0\1\7\2\220\1\101\1\0\1\102\5\0"+
+    "\5\7\1\220\1\7\1\220\1\7\1\220\3\7\2\220"+
+    "\7\7\27\0\14\221\1\0\10\221\1\222\1\223\4\221"+
+    "\1\0\56\221\14\224\1\0\11\224\1\225\1\226\3\224"+
+    "\1\0\56\224\1\0\10\7\1\220\1\7\2\0\2\7"+
+    "\1\0\1\7\1\0\1\7\2\220\1\101\1\0\1\102"+
+    "\5\0\1\144\3\7\1\145\1\220\1\7\1\220\1\7"+
+    "\1\220\3\7\2\220\7\7\30\0\10\7\1\220\1\7"+
+    "\2\0\2\7\1\0\1\7\1\0\1\7\2\220\1\101"+
+    "\1\0\1\102\5\0\5\7\1\227\1\7\1\220\1\7"+
+    "\1\220\3\7\2\220\7\7\30\0\10\7\1\220\1\7"+
+    "\2\0\2\7\1\0\1\7\1\0\1\7\2\220\1\101"+
+    "\1\0\1\102\5\0\5\7\1\220\1\7\1\220\1\7"+
+    "\1\220\1\150\1\151\1\7\2\220\7\7\30\0\10\7"+
+    "\1\220\1\7\2\0\2\7\1\0\1\7\1\0\1\7"+
+    "\2\220\1\101\1\0\1\102\5\0\5\7\1\230\1\7"+
+    "\1\220\1\7\1\220\1\7\1\161\1\162\2\220\7\7"+
+    "\42\0\1\231\14\0\1\232\2\0\1\233\57\0\1\110"+
+    "\1\111\1\110\1\0\1\110\1\0\1\113\2\0\1\116"+
+    "\4\0\1\117\1\120\1\0\1\121\16\0\1\120\5\0"+
+    "\1\116\43\0\3\111\1\0\1\111\1\0\1\234\7\0"+
+    "\1\117\1\120\1\0\1\121\16\0\1\120\51\0\5\235"+
+    "\1\0\1\236\1\0\1\235\6\0\1\235\2\0\1\235"+
+    "\11\0\1\235\1\0\1\235\1\0\1\235\2\0\1\235"+
+    "\1\0\1\235\4\0\1\235\37\0\1\110\1\111\1\110"+
+    "\1\0\1\110\105\0\1\237\1\0\1\237\1\0\1\237"+
+    "\1\0\1\240\103\0\1\241\3\0\1\241\1\0\1\242"+
+    "\103\0\3\124\1\0\1\124\12\0\1\120\1\0\1\121"+
+    "\16\0\1\120\51\0\3\243\1\0\1\243\13\0\1\244"+
+    "\41\0\1\244\27\0\3\6\1\0\1\6\105\0\10\7"+
+    "\1\245\1\7\2\0\2\7\1\0\1\7\1\0\1\7"+
+    "\2\245\1\14\1\0\1\16\5\0\5\7\1\245\1\7"+
+    "\1\245\1\7\1\245\3\7\2\245\7\7\30\0\3\124"+
+    "\1\0\1\124\1\0\1\246\10\0\1\120\1\0\1\121"+
+    "\16\0\1\120\50\0\14\127\1\0\10\127\1\247\1\131"+
+    "\4\127\1\132\56\127\25\0\1\250\1\251\1\0\2\252"+
+    "\1\0\2\132\55\0\112\127\14\133\1\0\11\133\1\134"+
+    "\1\247\3\133\1\132\170\133\26\0\1\251\1\253\2\252"+
+    "\1\0\2\132\56\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\2\7\1\254\23\7\30\0\12\7"+
     "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\3\7"+
-    "\1\331\22\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\15\7\1\332\10\7\30\0\12\7"+
-    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\1\333"+
-    "\25\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\3\7\1\334\22\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\6\7\1\335"+
-    "\17\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\7\7\1\336\16\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\13\7\1\337"+
-    "\12\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\22\7\1\340\3\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\1\341\25\7"+
+    "\1\255\22\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\6\7\1\256\17\7\30\0\12\7"+
+    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\12\7"+
+    "\1\257\3\7\1\260\7\7\30\0\12\7\2\0\2\7"+
+    "\1\0\1\7\1\0\3\7\10\0\3\7\1\261\10\7"+
+    "\1\262\11\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\11\7\1\263\14\7\30\0\12\7"+
+    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\14\7"+
+    "\1\264\11\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\6\7\1\265\17\7\30\0\12\7"+
+    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\21\7"+
+    "\1\266\4\7\30\0\10\7\1\245\1\7\2\0\2\7"+
+    "\1\0\1\7\1\0\1\7\2\245\1\14\1\0\1\16"+
+    "\5\0\4\7\1\267\1\245\1\7\1\245\1\7\1\245"+
+    "\3\7\2\245\7\7\30\0\12\7\2\0\2\7\1\0"+
+    "\1\7\1\0\3\7\10\0\1\270\25\7\30\0\12\7"+
+    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\1\7"+
+    "\1\271\24\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\22\7\1\272\3\7\30\0\12\7"+
+    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\20\7"+
+    "\1\273\5\7\30\0\10\7\1\245\1\7\2\0\2\7"+
+    "\1\0\1\7\1\0\1\7\2\245\1\14\1\0\1\16"+
+    "\5\0\5\7\1\245\1\7\1\245\1\7\1\245\1\7"+
+    "\1\274\1\7\2\245\7\7\30\0\12\7\2\0\2\7"+
+    "\1\0\1\7\1\0\3\7\10\0\5\7\1\275\20\7"+
     "\30\0\12\7\2\0\2\7\1\0\1\7\1\0\3\7"+
-    "\10\0\3\7\1\342\22\7\30\0\12\7\2\0\2\7"+
-    "\1\0\1\7\1\0\3\7\10\0\12\7\1\343\13\7"+
+    "\10\0\1\7\1\276\24\7\30\0\12\7\2\0\2\7"+
+    "\1\0\1\7\1\0\3\7\10\0\3\7\1\277\22\7"+
     "\30\0\12\7\2\0\2\7\1\0\1\7\1\0\3\7"+
-    "\10\0\7\7\1\344\16\7\30\0\12\7\2\0\2\7"+
-    "\1\0\1\7\1\0\3\7\10\0\12\7\1\345\13\7"+
-    "\54\0\1\346\1\0\1\347\110\0\1\310\1\0\2\311"+
-    "\1\0\2\213\55\0\25\307\1\350\1\351\63\307\26\312"+
-    "\1\352\1\353\62\312\1\0\12\7\2\0\2\7\1\0"+
-    "\1\7\1\0\3\7\1\354\1\0\1\355\5\0\26\7"+
-    "\27\0\25\315\1\356\1\357\63\315\26\316\1\360\1\361"+
-    "\62\316\25\0\1\362\113\0\1\363\62\0\25\246\1\364"+
-    "\1\365\175\246\140\251\1\366\1\367\62\251\1\0\12\7"+
+    "\10\0\4\7\1\300\21\7\30\0\12\7\2\0\2\7"+
+    "\1\0\1\7\1\0\3\7\10\0\13\7\1\301\12\7"+
+    "\30\0\12\7\2\0\2\7\1\0\1\7\1\0\3\7"+
+    "\10\0\14\7\1\302\11\7\113\0\1\303\111\0\1\304"+
+    "\111\0\1\305\111\0\1\306\36\0\1\307\11\0\2\307"+
+    "\1\75\1\0\1\76\12\0\1\307\1\0\1\307\1\0"+
+    "\1\307\3\0\2\307\36\0\14\211\1\0\10\211\1\310"+
+    "\1\213\4\211\1\214\56\211\25\0\1\311\1\312\1\0"+
+    "\2\313\1\0\2\214\55\0\112\211\14\215\1\0\11\215"+
+    "\1\216\1\310\3\215\1\214\170\215\26\0\1\312\1\314"+
+    "\2\313\1\0\2\214\56\0\10\7\1\315\1\7\2\0"+
+    "\2\7\1\0\1\7\1\0\1\7\2\315\1\101\1\0"+
+    "\1\102\5\0\5\7\1\315\1\7\1\315\1\7\1\315"+
+    "\3\7\2\315\7\7\27\0\14\221\1\0\10\221\1\316"+
+    "\1\223\4\221\1\0\56\221\25\0\1\317\64\0\112\221"+
+    "\14\224\1\0\11\224\1\225\1\316\3\224\1\0\170\224"+
+    "\27\0\1\320\63\0\10\7\1\315\1\7\2\0\2\7"+
+    "\1\0\1\7\1\0\1\7\2\315\1\101\1\0\1\102"+
+    "\5\0\4\7\1\267\1\315\1\7\1\315\1\7\1\315"+
+    "\3\7\2\315\7\7\30\0\10\7\1\315\1\7\2\0"+
+    "\2\7\1\0\1\7\1\0\1\7\2\315\1\101\1\0"+
+    "\1\102\5\0\5\7\1\315\1\7\1\315\1\7\1\315"+
+    "\1\7\1\274\1\7\2\315\7\7\27\0\14\231\1\0"+
+    "\16\231\1\233\56\231\1\0\3\111\1\0\1\111\105\0"+
+    "\5\235\1\0\1\236\1\0\1\235\1\116\5\0\1\235"+
+    "\2\0\1\235\11\0\1\235\1\0\1\235\1\0\1\235"+
+    "\2\0\1\235\1\0\1\235\1\116\3\0\1\235\37\0"+
+    "\5\235\3\0\1\235\6\0\1\235\2\0\1\235\11\0"+
+    "\1\235\1\0\1\235\1\0\1\235\2\0\1\235\1\0"+
+    "\1\235\4\0\1\235\37\0\1\237\1\0\1\237\1\0"+
+    "\1\237\1\0\1\240\2\0\1\116\34\0\1\116\43\0"+
+    "\1\237\1\0\1\237\1\0\1\237\105\0\1\241\3\0"+
+    "\1\241\1\0\1\242\2\0\1\116\34\0\1\116\43\0"+
+    "\1\241\3\0\1\241\105\0\3\243\1\0\1\243\1\0"+
+    "\1\244\12\0\1\121\70\0\3\243\1\0\1\243\105\0"+
+    "\12\7\2\0\2\7\1\0\1\7\1\0\3\7\1\14"+
+    "\1\0\1\16\5\0\26\7\55\0\1\251\1\0\2\252"+
+    "\1\0\2\132\55\0\25\250\1\321\1\322\63\250\26\253"+
+    "\1\323\1\324\62\253\1\0\12\7\2\0\2\7\1\0"+
+    "\1\7\1\0\3\7\10\0\4\7\1\325\21\7\30\0"+
+    "\12\7\2\0\2\7\1\0\1\7\1\0\3\7\10\0"+
+    "\4\7\1\326\21\7\30\0\12\7\2\0\2\7\1\0"+
+    "\1\7\1\0\3\7\10\0\16\7\1\327\7\7\30\0"+
+    "\12\7\2\0\2\7\1\0\1\7\1\0\3\7\10\0"+
+    "\4\7\1\330\21\7\30\0\12\7\2\0\2\7\1\0"+
+    "\1\7\1\0\3\7\10\0\3\7\1\331\22\7\30\0"+
+    "\12\7\2\0\2\7\1\0\1\7\1\0\3\7\10\0"+
+    "\15\7\1\332\10\7\30\0\12\7\2\0\2\7\1\0"+
+    "\1\7\1\0\3\7\10\0\1\333\25\7\30\0\12\7"+
+    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\3\7"+
+    "\1\334\22\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\6\7\1\335\17\7\30\0\12\7"+
+    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\7\7"+
+    "\1\336\16\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\13\7\1\337\12\7\30\0\12\7"+
+    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\22\7"+
+    "\1\340\3\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\1\341\25\7\30\0\12\7\2\0"+
+    "\2\7\1\0\1\7\1\0\3\7\10\0\3\7\1\342"+
+    "\22\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
+    "\3\7\10\0\12\7\1\343\13\7\30\0\12\7\2\0"+
+    "\2\7\1\0\1\7\1\0\3\7\10\0\7\7\1\344"+
+    "\16\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
+    "\3\7\10\0\12\7\1\345\13\7\54\0\1\75\1\0"+
+    "\1\76\110\0\1\312\1\0\2\313\1\0\2\214\55\0"+
+    "\25\311\1\346\1\347\63\311\26\314\1\350\1\351\62\314"+
+    "\1\0\12\7\2\0\2\7\1\0\1\7\1\0\3\7"+
+    "\1\101\1\0\1\102\5\0\26\7\27\0\25\317\1\352"+
+    "\1\353\63\317\26\320\1\354\1\355\62\320\25\250\1\356"+
+    "\1\357\175\250\140\253\1\360\1\361\62\253\1\0\12\7"+
     "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\5\7"+
-    "\1\370\20\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\20\7\1\371\5\7\30\0\12\7"+
+    "\1\362\20\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\20\7\1\363\5\7\30\0\12\7"+
     "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\4\7"+
-    "\1\372\21\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\5\7\1\373\20\7\30\0\12\7"+
+    "\1\364\21\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\5\7\1\365\20\7\30\0\12\7"+
     "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\10\7"+
-    "\1\374\15\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\3\7\1\375\22\7\30\0\12\7"+
+    "\1\366\15\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\3\7\1\367\22\7\30\0\12\7"+
     "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\14\7"+
-    "\1\376\11\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\2\7\1\377\23\7\30\0\12\7"+
+    "\1\370\11\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\2\7\1\371\23\7\30\0\12\7"+
     "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\5\7"+
-    "\1\u0100\20\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\12\7\1\u0101\13\7\30\0\12\7"+
+    "\1\372\20\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\12\7\1\373\13\7\30\0\12\7"+
     "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\2\7"+
-    "\1\u0102\23\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\1\u0103\25\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\4\7\1\u0104"+
-    "\21\7\54\0\1\u0105\113\0\1\u0106\62\0\25\307\1\u0107"+
-    "\1\u0108\175\307\140\312\1\u0109\1\u010a\62\312\25\0\1\u010b"+
-    "\113\0\1\u010c\62\0\25\315\1\u010d\1\u010e\175\315\140\316"+
-    "\1\u010f\1\u0110\62\316\25\0\1\246\113\0\1\251\62\0"+
-    "\25\246\1\u0111\1\365\110\246\1\u0112\1\365\63\246\26\251"+
-    "\1\366\1\u0113\110\251\1\366\1\u0111\62\251\1\0\12\7"+
-    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\6\7"+
-    "\1\u0114\17\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\6\7\1\u0115\17\7\30\0\12\7"+
-    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\1\7"+
-    "\1\u0116\24\7\30\0\12\7\2\0\2\7\1\0\1\7"+
-    "\1\0\3\7\10\0\1\7\1\u0117\24\7\30\0\12\7"+
-    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\1\u0118"+
-    "\25\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\6\7\1\u0119\17\7\30\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\12\7\1\u011a"+
-    "\13\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\12\7\1\u011b\13\7\54\0\1\307\113\0"+
-    "\1\312\62\0\25\307\1\u011c\1\u0108\110\307\1\u011d\1\u0108"+
-    "\63\307\26\312\1\u0109\1\u011e\110\312\1\u0109\1\u011c\62\312"+
-    "\25\315\1\u011f\1\u010e\110\315\1\u0120\1\u010e\63\315\26\316"+
-    "\1\u010f\1\u0121\110\316\1\u010f\1\u011f\62\316\26\0\1\u0122"+
-    "\1\0\2\u0123\1\0\2\u0124\55\0\25\246\1\u0125\1\365"+
-    "\63\246\26\251\1\366\1\u0126\62\251\1\0\12\7\2\0"+
-    "\2\7\1\0\1\7\1\0\3\7\10\0\15\7\1\u0127"+
-    "\10\7\30\0\12\7\2\0\2\7\1\0\1\7\1\0"+
-    "\3\7\10\0\21\7\1\u0128\4\7\27\0\25\307\1\u0129"+
-    "\1\u0108\63\307\26\312\1\u0109\1\u012a\62\312\25\315\1\u012b"+
-    "\1\u010e\63\315\26\316\1\u010f\1\u012c\62\316\25\246\1\u012d"+
-    "\1\365\63\246\26\251\1\366\1\u012e\62\251\1\0\12\7"+
-    "\2\0\2\7\1\0\1\7\1\0\3\7\10\0\4\7"+
-    "\1\u012f\21\7\27\0\25\307\1\u0130\1\u0108\63\307\26\312"+
-    "\1\u0109\1\u0131\62\312\25\315\1\u0132\1\u010e\63\315\26\316"+
-    "\1\u010f\1\u0133\62\316";
+    "\1\374\23\7\30\0\12\7\2\0\2\7\1\0\1\7"+
+    "\1\0\3\7\10\0\1\375\25\7\30\0\12\7\2\0"+
+    "\2\7\1\0\1\7\1\0\3\7\10\0\4\7\1\376"+
+    "\21\7\27\0\25\311\1\377\1\u0100\175\311\140\314\1\u0101"+
+    "\1\u0102\62\314\25\317\1\u0103\1\u0104\175\317\140\320\1\u0105"+
+    "\1\u0106\62\320\25\250\1\u0107\1\357\110\250\1\u0108\1\357"+
+    "\63\250\26\253\1\360\1\u0109\110\253\1\360\1\u0107\62\253"+
+    "\1\0\12\7\2\0\2\7\1\0\1\7\1\0\3\7"+
+    "\10\0\6\7\1\u010a\17\7\30\0\12\7\2\0\2\7"+
+    "\1\0\1\7\1\0\3\7\10\0\6\7\1\u010b\17\7"+
+    "\30\0\12\7\2\0\2\7\1\0\1\7\1\0\3\7"+
+    "\10\0\1\7\1\u010c\24\7\30\0\12\7\2\0\2\7"+
+    "\1\0\1\7\1\0\3\7\10\0\1\7\1\u010d\24\7"+
+    "\30\0\12\7\2\0\2\7\1\0\1\7\1\0\3\7"+
+    "\10\0\1\u010e\25\7\30\0\12\7\2\0\2\7\1\0"+
+    "\1\7\1\0\3\7\10\0\6\7\1\u010f\17\7\30\0"+
+    "\12\7\2\0\2\7\1\0\1\7\1\0\3\7\10\0"+
+    "\12\7\1\u0110\13\7\30\0\12\7\2\0\2\7\1\0"+
+    "\1\7\1\0\3\7\10\0\12\7\1\u0111\13\7\27\0"+
+    "\25\311\1\u0112\1\u0100\110\311\1\u0113\1\u0100\63\311\26\314"+
+    "\1\u0101\1\u0114\110\314\1\u0101\1\u0112\62\314\25\317\1\u0115"+
+    "\1\u0104\110\317\1\u0116\1\u0104\63\317\26\320\1\u0105\1\u0117"+
+    "\110\320\1\u0105\1\u0115\62\320\26\0\1\u0118\1\0\2\u0119"+
+    "\1\0\2\u011a\55\0\25\250\1\u011b\1\357\63\250\26\253"+
+    "\1\360\1\u011c\62\253\1\0\12\7\2\0\2\7\1\0"+
+    "\1\7\1\0\3\7\10\0\15\7\1\u011d\10\7\30\0"+
+    "\12\7\2\0\2\7\1\0\1\7\1\0\3\7\10\0"+
+    "\21\7\1\u011e\4\7\27\0\25\311\1\u011f\1\u0100\63\311"+
+    "\26\314\1\u0101\1\u0120\62\314\25\317\1\u0121\1\u0104\63\317"+
+    "\26\320\1\u0105\1\u0122\62\320\25\250\1\u0123\1\357\63\250"+
+    "\26\253\1\360\1\u0124\62\253\1\0\12\7\2\0\2\7"+
+    "\1\0\1\7\1\0\3\7\10\0\4\7\1\u0125\21\7"+
+    "\27\0\25\311\1\u0126\1\u0100\63\311\26\314\1\u0101\1\u0127"+
+    "\62\314\25\317\1\u0128\1\u0104\63\317\26\320\1\u0105\1\u0129"+
+    "\62\320";
 
   private static int [] zzUnpackTrans() {
-    int [] result = new int[16132];
+    int [] result = new int[15540];
     int offset = 0;
     offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
     return result;
@@ -591,19 +597,19 @@ class _PythonLexer implements FlexLexer {
 
   private static final String ZZ_ATTRIBUTE_PACKED_0 =
     "\3\0\1\11\10\1\1\11\1\1\5\11\34\1\13\11"+
-    "\4\1\1\11\10\1\5\0\1\11\1\1\1\0\1\11"+
+    "\4\1\1\11\11\1\5\0\1\11\1\1\1\0\1\11"+
     "\1\0\2\1\2\11\3\1\1\11\34\1\3\11\1\1"+
     "\2\11\1\1\5\11\1\1\2\11\1\1\1\11\1\0"+
-    "\3\1\1\11\13\1\2\0\1\11\1\0\1\1\1\0"+
+    "\3\1\1\11\14\1\2\0\1\11\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\30\1\4\11\1\0\2\1\1\11"+
-    "\1\0\2\1\1\11\2\1\3\0\2\1\1\0\21\1"+
-    "\3\0\2\1\12\0\2\1\1\0\15\1\3\0\2\1"+
-    "\4\0\2\1\1\0\16\1\1\11\2\1\1\11\1\0"+
+    "\1\0\2\1\1\11\2\1\1\0\2\1\1\0\21\1"+
+    "\1\0\2\1\6\0\2\1\1\0\15\1\1\0\2\1"+
+    "\2\0\2\1\1\0\16\1\1\11\2\1\1\11\1\0"+
     "\1\11\2\0\2\1\4\0\7\1";
 
   private static int [] zzUnpackAttribute() {
-    int [] result = new int[307];
+    int [] result = new int[297];
     int offset = 0;
     offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
     return result;
index 1606ac65d543b04e286b5da276ad48107902feda..20ec3a9b52512d5f6a74cfe7d5a85179da702161 100644 (file)
@@ -48,6 +48,7 @@ public class PyStringLiteralLexer extends LexerBase {
 
   private boolean myIsRaw;
   private boolean myIsTriple;
+  private boolean myIsFormatted;
   private final IElementType myOriginalLiteralToken;
   private boolean mySeenEscapedSpacesOnly;
 
@@ -74,6 +75,9 @@ public class PyStringLiteralLexer extends LexerBase {
     int offset = skipRawPrefix(buffer, i);
     if (offset > i) myIsRaw = true;
     i = offset;
+    offset = skipFormattedPrefix(buffer, i);
+    if (offset > i) myIsFormatted = true;
+    i = offset;
     i = skipEncodingPrefix(buffer, i);
     offset = skipRawPrefix(buffer, i);
     if (offset > i) myIsRaw = true;
@@ -90,6 +94,14 @@ public class PyStringLiteralLexer extends LexerBase {
     myEnd = locateToken(myStart);
   }
 
+  public static int skipFormattedPrefix(CharSequence text, int startOffset) {
+    char c = Character.toUpperCase(text.charAt(startOffset));
+    if (c == 'F') {
+      startOffset++;
+    }
+    return startOffset;
+  }
+
   public static int skipRawPrefix(CharSequence text, int startOffset) {
     char c = Character.toUpperCase(text.charAt(startOffset));
     if (c == 'R') {
index 6450207ab542fe923d56df3f3aa1d8331ea05434..c7f49f080c657cc48cbbf7557257f10c0b326d87 100644 (file)
@@ -46,8 +46,8 @@ IMAGNUMBER=(({FLOATNUMBER})|({INTPART}))[Jj]
 //RAW_STRING=[Rr]{QUOTED_STRING}
 //QUOTED_STRING=({TRIPLE_APOS_LITERAL})|({QUOTED_LITERAL})|({DOUBLE_QUOTED_LITERAL})|({TRIPLE_QUOTED_LITERAL})
 
-SINGLE_QUOTED_STRING=[UuBbCcRr]{0,2}({QUOTED_LITERAL} | {DOUBLE_QUOTED_LITERAL})
-TRIPLE_QUOTED_STRING=[UuBbCcRr]{0,2}[UuBbCcRr]?({TRIPLE_QUOTED_LITERAL}|{TRIPLE_APOS_LITERAL})
+SINGLE_QUOTED_STRING=[UuBbCcRrFf]{0,3}({QUOTED_LITERAL} | {DOUBLE_QUOTED_LITERAL})
+TRIPLE_QUOTED_STRING=[UuBbCcRrFf]{0,3}({TRIPLE_QUOTED_LITERAL}|{TRIPLE_APOS_LITERAL})
 
 DOCSTRING_LITERAL=({SINGLE_QUOTED_STRING}|{TRIPLE_QUOTED_STRING})
 
index d2bc6f5bc3e5a071754365a1f82c69cfcee55440..212dadf48f467c5ae7c833468542e7f6ebb3fc23 100644 (file)
@@ -135,6 +135,7 @@ public class PyStringLiteralExpressionImpl extends PyElementImpl implements PySt
     int startOffset = 0;
     startOffset = PyStringLiteralLexer.skipEncodingPrefix(text, startOffset);
     startOffset = PyStringLiteralLexer.skipRawPrefix(text, startOffset);
+    startOffset = PyStringLiteralLexer.skipFormattedPrefix(text, startOffset);
     startOffset = PyStringLiteralLexer.skipEncodingPrefix(text, startOffset);
     startOffset = PyStringLiteralLexer.skipRawPrefix(text, startOffset);
     return startOffset;
index fafbaca04a3181dfd8fbd516f9f66537573d5ef2..0be080329b5dc42e2efa635ca52e3b980592ab27 100644 (file)
@@ -52,6 +52,7 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
     AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON30, Sets.newHashSet("R", "B"));
     AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON31, Sets.newHashSet("R", "B", "BR"));
     AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON32, Sets.newHashSet("R", "B", "BR"));
+    AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON36, Sets.newHashSet("R", "U", "B", "BR", "RB", "F", "FR", "RF"));
   }
 
   private static final Set<String> DEFAULT_PREFIXES = Sets.newHashSet(Sets.newHashSet("R", "U", "B", "BR", "RB"));
diff --git a/python/testData/highlighting/fStringLiterals.py b/python/testData/highlighting/fStringLiterals.py
new file mode 100644 (file)
index 0000000..f9d47a0
--- /dev/null
@@ -0,0 +1,9 @@
+a = <error descr="Python version 2.7 does not support a 'F' prefix">f</error>""
+a = <error descr="Python version 2.7 does not support a 'F' prefix">F</error>""
+a = <error descr="Python version 2.7 does not support a 'RF' prefix">rf</error>""
+a = <error descr="Python version 2.7 does not support a 'FR' prefix">fr</error>""
+a = <error descr="Python version 2.7 does not support a 'FU' prefix">fu</error>""
+a = <error descr="Python version 2.7 does not support a 'UF' prefix">uf</error>""
+a = <error descr="Python version 2.7 does not support a 'BF' prefix">bf</error>""
+a = <error descr="Python version 2.7 does not support a 'FB' prefix">fb</error>""
+a = <error descr="Python version 2.7 does not support a 'UFR' prefix">ufr</error>""
index aba46f914952608963bd3e3ede4fdfde9d7caa3d..93e7740bf8096e9c818dd648895529b015526012 100644 (file)
@@ -1,5 +1,17 @@
 a = <warning descr="Python version 3.0, 3.1, 3.2 do not support a 'U' prefix">u</warning>"String"
 
+# Python 3.6
+
+a = <error descr="Python version 2.7 does not support a 'F' prefix"><warning descr="Python version 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5 do not support a 'F' prefix">f</warning></error>""
+a = <error descr="Python version 2.7 does not support a 'F' prefix"><warning descr="Python version 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5 do not support a 'F' prefix">F</warning></error>""
+a = <error descr="Python version 2.7 does not support a 'RF' prefix"><warning descr="Python version 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5 do not support a 'RF' prefix">rf</warning></error>""
+a = <error descr="Python version 2.7 does not support a 'FR' prefix"><warning descr="Python version 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5 do not support a 'FR' prefix">fr</warning></error>""
+a = <error descr="Python version 2.7 does not support a 'FU' prefix"><warning descr="Python version 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6 do not support a 'FU' prefix">fu</warning></error>""
+a = <error descr="Python version 2.7 does not support a 'UF' prefix"><warning descr="Python version 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6 do not support a 'UF' prefix">uf</warning></error>""
+a = <error descr="Python version 2.7 does not support a 'BF' prefix"><warning descr="Python version 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6 do not support a 'BF' prefix">bf</warning></error>""
+a = <error descr="Python version 2.7 does not support a 'FB' prefix"><warning descr="Python version 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6 do not support a 'FB' prefix">fb</warning></error>""
+a = <error descr="Python version 2.7 does not support a 'UFR' prefix"><warning descr="Python version 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6 do not support a 'UFR' prefix">ufr</warning></error>""
+
 # python 3.3
 
 a = <warning descr="Python version 3.0, 3.1, 3.2 do not support a 'U' prefix">u</warning>""
diff --git a/python/testData/intentions/removeLeadingF.py b/python/testData/intentions/removeLeadingF.py
new file mode 100644 (file)
index 0000000..8eb9f65
--- /dev/null
@@ -0,0 +1 @@
+a = <caret>f"{42}"
\ No newline at end of file
diff --git a/python/testData/intentions/removeLeadingF_after.py b/python/testData/intentions/removeLeadingF_after.py
new file mode 100644 (file)
index 0000000..641404c
--- /dev/null
@@ -0,0 +1 @@
+a = <caret>"{42}"
\ No newline at end of file
diff --git a/python/testData/psi/FStrings.py b/python/testData/psi/FStrings.py
new file mode 100644 (file)
index 0000000..24ebfa1
--- /dev/null
@@ -0,0 +1,7 @@
+s1 = f'' 
+s2 = fr''
+s3 = rf''
+s4 = F''
+s5 = bf''
+s6 = uf''
+s7 = ufr''
diff --git a/python/testData/psi/FStrings.txt b/python/testData/psi/FStrings.txt
new file mode 100644 (file)
index 0000000..d7825d5
--- /dev/null
@@ -0,0 +1,63 @@
+PyFile:FStrings.py
+  PyAssignmentStatement
+    PyTargetExpression: s1
+      PsiElement(Py:IDENTIFIER)('s1')
+    PsiWhiteSpace(' ')
+    PsiElement(Py:EQ)('=')
+    PsiWhiteSpace(' ')
+    PyStringLiteralExpression: 
+      PsiElement(Py:SINGLE_QUOTED_STRING)('f''')
+  PsiWhiteSpace(' \n')
+  PyAssignmentStatement
+    PyTargetExpression: s2
+      PsiElement(Py:IDENTIFIER)('s2')
+    PsiWhiteSpace(' ')
+    PsiElement(Py:EQ)('=')
+    PsiWhiteSpace(' ')
+    PyStringLiteralExpression: 
+      PsiElement(Py:SINGLE_QUOTED_STRING)('fr''')
+  PsiWhiteSpace('\n')
+  PyAssignmentStatement
+    PyTargetExpression: s3
+      PsiElement(Py:IDENTIFIER)('s3')
+    PsiWhiteSpace(' ')
+    PsiElement(Py:EQ)('=')
+    PsiWhiteSpace(' ')
+    PyStringLiteralExpression: 
+      PsiElement(Py:SINGLE_QUOTED_STRING)('rf''')
+  PsiWhiteSpace('\n')
+  PyAssignmentStatement
+    PyTargetExpression: s4
+      PsiElement(Py:IDENTIFIER)('s4')
+    PsiWhiteSpace(' ')
+    PsiElement(Py:EQ)('=')
+    PsiWhiteSpace(' ')
+    PyStringLiteralExpression: 
+      PsiElement(Py:SINGLE_QUOTED_STRING)('F''')
+  PsiWhiteSpace('\n')
+  PyAssignmentStatement
+    PyTargetExpression: s5
+      PsiElement(Py:IDENTIFIER)('s5')
+    PsiWhiteSpace(' ')
+    PsiElement(Py:EQ)('=')
+    PsiWhiteSpace(' ')
+    PyStringLiteralExpression: 
+      PsiElement(Py:SINGLE_QUOTED_STRING)('bf''')
+  PsiWhiteSpace('\n')
+  PyAssignmentStatement
+    PyTargetExpression: s6
+      PsiElement(Py:IDENTIFIER)('s6')
+    PsiWhiteSpace(' ')
+    PsiElement(Py:EQ)('=')
+    PsiWhiteSpace(' ')
+    PyStringLiteralExpression: 
+      PsiElement(Py:SINGLE_QUOTED_STRING)('uf''')
+  PsiWhiteSpace('\n')
+  PyAssignmentStatement
+    PyTargetExpression: s7
+      PsiElement(Py:IDENTIFIER)('s7')
+    PsiWhiteSpace(' ')
+    PsiElement(Py:EQ)('=')
+    PsiWhiteSpace(' ')
+    PyStringLiteralExpression: 
+      PsiElement(Py:SINGLE_QUOTED_STRING)('ufr''')
\ No newline at end of file
index 5991a6d16135b1b6bc08dde49040f96f1cc4f18d..25f1fcff2fc31b21bf2713c036cd082b072169bf 100644 (file)
@@ -301,6 +301,10 @@ public class PythonHighlightingTest extends PyTestCase {
     doTest(LanguageLevel.PYTHON36, true, false);
   }
 
+  public void testFStringLiterals() {
+    doTest();
+  }
+
   // ---
   private void doTest(final LanguageLevel languageLevel, final boolean checkWarnings, final boolean checkInfos) {
     PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), languageLevel);
index 4398fdd77be04524ecb97e355858d8380f13ac4a..644496dd0a703e7951b6413ddc8c7e97f73ca335 100644 (file)
@@ -388,6 +388,13 @@ public class PythonLexerTest extends PyLexerTestCase {
     doTest("10_000_000J", "Py:IMAGINARY_LITERAL", "Py:STATEMENT_BREAK");
   }
 
+  public void testFStringLiterals() {
+    doTest("s = f'{x}'", "Py:IDENTIFIER", "Py:SPACE", "Py:EQ", "Py:SPACE", "Py:SINGLE_QUOTED_STRING", "Py:STATEMENT_BREAK");
+    doTest("s = rf\"{x}\"", "Py:IDENTIFIER", "Py:SPACE", "Py:EQ", "Py:SPACE", "Py:SINGLE_QUOTED_STRING", "Py:STATEMENT_BREAK");
+    doTest("s = fr'''{x}\n'''", "Py:IDENTIFIER", "Py:SPACE", "Py:EQ", "Py:SPACE", "Py:TRIPLE_QUOTED_STRING", "Py:STATEMENT_BREAK");
+    doTest("s = f\"\"\"{x}\n\"\"\"", "Py:IDENTIFIER", "Py:SPACE", "Py:EQ", "Py:SPACE", "Py:TRIPLE_QUOTED_STRING", "Py:STATEMENT_BREAK");
+  }
+
   private static void doTest(String text, String... expectedTokens) {
     PyLexerTestCase.doLexerTest(text, new PythonIndentingLexer(), expectedTokens);
   }
index e90e63aff9f7fa19812e449b49c8d2307caf4538..605b56ac0d78df15a81524835ee9f9cc1121c779 100644 (file)
@@ -506,6 +506,11 @@ public class PythonParsingTest extends ParsingTestCase {
     doTest(LanguageLevel.PYTHON35);
   }
 
+  // PY-18972
+  public void testFStrings() {
+    doTest(LanguageLevel.PYTHON36);
+  }
+
   // PY-19036
   public void testAwaitInNonAsyncNestedFunction() {
     doTest(LanguageLevel.PYTHON35);
index 53d2dc40c315246b0be9560466f845cab44bb3ed..5aeb68f87bcb7f5033452987ce7fcb0644498b1e 100644 (file)
@@ -105,6 +105,11 @@ public class  PyIntentionTest extends PyTestCase {
     doTest(PyBundle.message("INTN.remove.leading.$0", "U"), LanguageLevel.PYTHON30);
   }
 
+  public void testRemoveLeadingF() {
+    doTest(PyBundle.message("INTN.remove.leading.$0", "F"), LanguageLevel.PYTHON35);
+  }
+
+  // PY-18972
   public void testRemoveTrailingL() {
     doTest(PyBundle.message("INTN.remove.trailing.l"), LanguageLevel.PYTHON30);
   }