From 11bcc65927475a5c38332ee1ace4a64149b59d6a Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 3 Feb 2017 19:14:38 -0500
Subject: [PATCH 01/65] Clarify why scopes for 'f' string prefix are ordered
 the way they are

---
 grammars/src/pyfstring.inc.syntax.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/grammars/src/pyfstring.inc.syntax.yaml b/grammars/src/pyfstring.inc.syntax.yaml
index 0d167d2a..8a0a31c2 100644
--- a/grammars/src/pyfstring.inc.syntax.yaml
+++ b/grammars/src/pyfstring.inc.syntax.yaml
@@ -5,6 +5,11 @@ repository:
     begin: (\b[fF])([bBuU])?(${marker})
     end: (\3)${guard}
     beginCaptures:
+      # "storage.type.string.python" class should be the first one,
+      # because Atom, VSCode and GitHub don't understand scopes
+      # separated by whitespace, and simply use the first one
+      # of them.  Highlighting 'f' as 'storage.type' is more
+      # important for us than having other scopes.
       '1': {name: storage.type.string.python
                   string.quoted.${line}.python
                   string.interpolated.python}

From 86ccbfdb1bb3219a14ab3b4a7b6a54c1aa2484d2 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 3 Feb 2017 19:29:28 -0500
Subject: [PATCH 02/65] Highlight class parameters as kwargs in Atom/VSCode/GH.

---
 grammars/MagicPython.cson            | 2 +-
 grammars/MagicPython.tmLanguage      | 2 +-
 grammars/src/MagicPython.syntax.yaml | 7 +++++--
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index d014bf33..3f9fa44f 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -1124,7 +1124,7 @@ repository:
     '''
     captures:
       "1":
-        name: "entity.other.inherited-class.python variable.parameter.class.python"
+        name: "variable.parameter.class.python entity.other.inherited-class.python"
       "2":
         name: "keyword.operator.assignment.python"
   "inheritance-identifier":
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 380a36de..92b93020 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -1733,7 +1733,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>entity.other.inherited-class.python variable.parameter.class.python</string>
+            <string>variable.parameter.class.python entity.other.inherited-class.python</string>
           </dict>
           <key>2</key>
           <dict>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 7da44ccc..589f7741 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -895,8 +895,11 @@ repository:
       (?x)
         \b ([[:alpha:]_]\w*) \s*(=)(?!=)
     captures:
-      '1': {name: entity.other.inherited-class.python
-                  variable.parameter.class.python}
+      # "variable.parameter.class.python" scope is more important
+      # and hence we specify it first to highlight class parameters
+      # as kwargs in Atom/VSCode/GH.
+      '1': {name: variable.parameter.class.python
+                  entity.other.inherited-class.python}
       '2': {name: keyword.operator.assignment.python}
 
   inheritance-identifier:

From 6e5118304a7c4da2195d10c29e5f15625437c18a Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 3 Feb 2017 19:32:24 -0500
Subject: [PATCH 03/65] Prepare 1.0.5 release

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 58e185d2..caf6f1ba 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "MagicPython",
-  "version": "1.0.4",
+  "version": "1.0.5",
   "engines": {
     "atom": "*",
     "node": "*",

From c705cd1d18d4e75c5da93f4eacca544a85baebb4 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Fri, 3 Feb 2017 20:21:27 -0500
Subject: [PATCH 04/65] Add an important note about the importance of scope
 ordering.

---
 README.md | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/README.md b/README.md
index f8a9ce1a..dd281085 100644
--- a/README.md
+++ b/README.md
@@ -229,6 +229,19 @@ If you intend to submit a pull request, please follow the following guidelines:
 - update unit tests and add new ones if needed, keeping the test cases short
   whenever possible
 
+### Multiple scopes
+
+It is sometimes necessary to assign multiple scopes to the same
+matched group. It is *very important* to keep in mind that the order
+of these scopes is apparently treated as significant by the engines
+processing the grammar specs. However, it is equally important to know
+that different specification formats seem to have different order of
+importance (most important first vs. last). Since we try to create
+grammar that can be compiled into several different formats, we must
+chose one convention and then translate it when necessary during
+compilation step. Our convention is therefore that *most important
+scope goes first*.
+
 ## Color Scheme
 
 If you want to write your own color scheme for MagicPython you can

From df5bb18c64252f2e7b1aa87e2ed124666d314f1d Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 3 Feb 2017 20:40:30 -0500
Subject: [PATCH 05/65] Bump the version of syntaxdev to v0.0.12; fix
 regression in ST.

---
 Makefile                        |   2 +-
 grammars/MagicPython.tmLanguage | 250 ++++++++++++++++----------------
 grammars/MagicRegExp.tmLanguage |  30 ++--
 3 files changed, 141 insertions(+), 141 deletions(-)

diff --git a/Makefile b/Makefile
index 8932961d..3ecb8621 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ test: release
 		then echo "Error: package.version != git.tag" && exit 1 ; fi
 
 devenv:
-	npm install syntaxdev@0.0.11
+	npm install syntaxdev@0.0.12
 
 release:
 	./node_modules/.bin/syntaxdev build-plist --in grammars/src/MagicPython.syntax.yaml --out grammars/MagicPython.tmLanguage
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 92b93020..fe97f739 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -1733,7 +1733,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>variable.parameter.class.python entity.other.inherited-class.python</string>
+            <string>entity.other.inherited-class.python variable.parameter.class.python</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3060,7 +3060,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.backreference.named.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.backreference.named.begin.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3070,7 +3070,7 @@ indirectly through syntactic constructs
           <key>3</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.backreference.named.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.backreference.named.end.regexp</string>
           </dict>
         </dict>
       </dict>
@@ -3332,7 +3332,7 @@ indirectly through syntactic constructs
               <key>1</key>
               <dict>
                 <key>name</key>
-                <string>constant.other.set.regexp punctuation.character.set.begin.regexp</string>
+                <string>punctuation.character.set.begin.regexp constant.other.set.regexp</string>
               </dict>
               <key>2</key>
               <dict>
@@ -3350,7 +3350,7 @@ indirectly through syntactic constructs
               <key>1</key>
               <dict>
                 <key>name</key>
-                <string>constant.other.set.regexp punctuation.character.set.end.regexp</string>
+                <string>punctuation.character.set.end.regexp constant.other.set.regexp</string>
               </dict>
               <key>2</key>
               <dict>
@@ -3389,7 +3389,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3402,7 +3402,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3479,7 +3479,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp</string>
+            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3519,7 +3519,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp</string>
+            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3559,7 +3559,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp</string>
+            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3599,7 +3599,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp</string>
+            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3639,7 +3639,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp</string>
+            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3666,7 +3666,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -3674,7 +3674,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3701,7 +3701,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -3709,7 +3709,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3809,7 +3809,7 @@ indirectly through syntactic constructs
               <key>1</key>
               <dict>
                 <key>name</key>
-                <string>constant.other.set.regexp punctuation.character.set.begin.regexp</string>
+                <string>punctuation.character.set.begin.regexp constant.other.set.regexp</string>
               </dict>
               <key>2</key>
               <dict>
@@ -3827,7 +3827,7 @@ indirectly through syntactic constructs
               <key>1</key>
               <dict>
                 <key>name</key>
-                <string>constant.other.set.regexp punctuation.character.set.end.regexp</string>
+                <string>punctuation.character.set.end.regexp constant.other.set.regexp</string>
               </dict>
               <key>2</key>
               <dict>
@@ -3866,7 +3866,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3879,7 +3879,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -3960,7 +3960,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp</string>
+            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4004,7 +4004,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp</string>
+            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4048,7 +4048,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp</string>
+            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4092,7 +4092,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp</string>
+            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4136,7 +4136,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp</string>
+            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4167,7 +4167,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -4175,7 +4175,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4206,7 +4206,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -4214,7 +4214,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4314,7 +4314,7 @@ indirectly through syntactic constructs
               <key>1</key>
               <dict>
                 <key>name</key>
-                <string>constant.other.set.regexp punctuation.character.set.begin.regexp</string>
+                <string>punctuation.character.set.begin.regexp constant.other.set.regexp</string>
               </dict>
               <key>2</key>
               <dict>
@@ -4332,7 +4332,7 @@ indirectly through syntactic constructs
               <key>1</key>
               <dict>
                 <key>name</key>
-                <string>constant.other.set.regexp punctuation.character.set.end.regexp</string>
+                <string>punctuation.character.set.end.regexp constant.other.set.regexp</string>
               </dict>
               <key>2</key>
               <dict>
@@ -4371,7 +4371,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4384,7 +4384,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4461,7 +4461,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp</string>
+            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4501,7 +4501,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp</string>
+            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4541,7 +4541,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp</string>
+            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4581,7 +4581,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp</string>
+            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4621,7 +4621,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp</string>
+            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4648,7 +4648,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -4656,7 +4656,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4683,7 +4683,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -4691,7 +4691,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4791,7 +4791,7 @@ indirectly through syntactic constructs
               <key>1</key>
               <dict>
                 <key>name</key>
-                <string>constant.other.set.regexp punctuation.character.set.begin.regexp</string>
+                <string>punctuation.character.set.begin.regexp constant.other.set.regexp</string>
               </dict>
               <key>2</key>
               <dict>
@@ -4809,7 +4809,7 @@ indirectly through syntactic constructs
               <key>1</key>
               <dict>
                 <key>name</key>
-                <string>constant.other.set.regexp punctuation.character.set.end.regexp</string>
+                <string>punctuation.character.set.end.regexp constant.other.set.regexp</string>
               </dict>
               <key>2</key>
               <dict>
@@ -4848,7 +4848,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4861,7 +4861,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4942,7 +4942,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp</string>
+            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -4986,7 +4986,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp</string>
+            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5030,7 +5030,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp</string>
+            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5074,7 +5074,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp</string>
+            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5118,7 +5118,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp</string>
+            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5149,7 +5149,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -5157,7 +5157,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5188,7 +5188,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -5196,7 +5196,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5497,7 +5497,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5510,7 +5510,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5550,7 +5550,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp</string>
+            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5590,7 +5590,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp</string>
+            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5630,7 +5630,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp</string>
+            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5670,7 +5670,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp</string>
+            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5710,7 +5710,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp</string>
+            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5737,7 +5737,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -5745,7 +5745,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5772,7 +5772,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -5780,7 +5780,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5873,7 +5873,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5886,7 +5886,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5930,7 +5930,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp</string>
+            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -5974,7 +5974,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp</string>
+            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6018,7 +6018,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp</string>
+            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6062,7 +6062,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp</string>
+            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6106,7 +6106,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp</string>
+            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6137,7 +6137,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -6145,7 +6145,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6176,7 +6176,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -6184,7 +6184,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6277,7 +6277,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6290,7 +6290,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6330,7 +6330,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp</string>
+            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6370,7 +6370,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp</string>
+            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6410,7 +6410,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp</string>
+            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6450,7 +6450,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp</string>
+            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6490,7 +6490,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp</string>
+            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6517,7 +6517,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -6525,7 +6525,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6552,7 +6552,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -6560,7 +6560,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6653,7 +6653,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6666,7 +6666,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6710,7 +6710,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp</string>
+            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6754,7 +6754,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp</string>
+            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6798,7 +6798,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp</string>
+            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6842,7 +6842,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp</string>
+            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6886,7 +6886,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp</string>
+            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6917,7 +6917,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -6925,7 +6925,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6956,7 +6956,7 @@ indirectly through syntactic constructs
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -6964,7 +6964,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -6987,7 +6987,7 @@ indirectly through syntactic constructs
       <key>fregexp-single-one-line</key>
       <dict>
         <key>name</key>
-        <string>string.regexp.quoted.single.python string.interpolated.python</string>
+        <string>string.interpolated.python string.regexp.quoted.single.python</string>
         <key>begin</key>
         <string>\b(([uU]r)|([fF]r)|(r[fF]?))(\')</string>
         <key>end</key>
@@ -7039,7 +7039,7 @@ indirectly through syntactic constructs
       <key>fregexp-single-three-line</key>
       <dict>
         <key>name</key>
-        <string>string.regexp.quoted.multi.python string.interpolated.python</string>
+        <string>string.interpolated.python string.regexp.quoted.multi.python</string>
         <key>begin</key>
         <string>\b(([uU]r)|([fF]r)|(r[fF]?))(\'\'\')</string>
         <key>end</key>
@@ -7091,7 +7091,7 @@ indirectly through syntactic constructs
       <key>fregexp-double-one-line</key>
       <dict>
         <key>name</key>
-        <string>string.regexp.quoted.single.python string.interpolated.python</string>
+        <string>string.interpolated.python string.regexp.quoted.single.python</string>
         <key>begin</key>
         <string>\b(([uU]r)|([fF]r)|(r[fF]?))(")</string>
         <key>end</key>
@@ -7143,7 +7143,7 @@ indirectly through syntactic constructs
       <key>fregexp-double-three-line</key>
       <dict>
         <key>name</key>
-        <string>string.regexp.quoted.multi.python string.interpolated.python</string>
+        <string>string.interpolated.python string.regexp.quoted.multi.python</string>
         <key>begin</key>
         <string>\b(([uU]r)|([fF]r)|(r[fF]?))(""")</string>
         <key>end</key>
@@ -7805,7 +7805,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>storage.type.string.python string.quoted.single.python string.interpolated.python</string>
+            <string>string.interpolated.python string.quoted.single.python storage.type.string.python</string>
           </dict>
           <key>2</key>
           <dict>
@@ -7815,7 +7815,7 @@ indirectly through syntactic constructs
           <key>3</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python</string>
+            <string>punctuation.definition.string.begin.python string.interpolated.python string.quoted.single.python</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -7823,7 +7823,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python</string>
+            <string>punctuation.definition.string.end.python string.interpolated.python string.quoted.single.python</string>
           </dict>
           <key>2</key>
           <dict>
@@ -7869,12 +7869,12 @@ indirectly through syntactic constructs
           <key>2</key>
           <dict>
             <key>name</key>
-            <string>storage.type.string.python string.quoted.single.python string.interpolated.python</string>
+            <string>string.interpolated.python string.quoted.single.python storage.type.string.python</string>
           </dict>
           <key>3</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.single.python punctuation.definition.string.begin.python</string>
+            <string>punctuation.definition.string.begin.python string.quoted.single.python</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -7882,7 +7882,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python</string>
+            <string>punctuation.definition.string.end.python string.interpolated.python string.quoted.single.python</string>
           </dict>
           <key>2</key>
           <dict>
@@ -7923,12 +7923,12 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>storage.type.string.python string.quoted.raw.single.python string.interpolated.python</string>
+            <string>string.interpolated.python string.quoted.raw.single.python storage.type.string.python</string>
           </dict>
           <key>2</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.raw.single.python punctuation.definition.string.begin.python</string>
+            <string>punctuation.definition.string.begin.python string.quoted.raw.single.python</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -7936,7 +7936,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python</string>
+            <string>punctuation.definition.string.end.python string.interpolated.python string.quoted.raw.single.python</string>
           </dict>
           <key>2</key>
           <dict>
@@ -7967,7 +7967,7 @@ indirectly through syntactic constructs
       <key>fstring-single-core</key>
       <dict>
         <key>name</key>
-        <string>string.quoted.single.python string.interpolated.python</string>
+        <string>string.interpolated.python string.quoted.single.python</string>
         <key>match</key>
         <string>(?x)
   (.+?)
@@ -7990,7 +7990,7 @@ indirectly through syntactic constructs
       <key>fstring-raw-single-core</key>
       <dict>
         <key>name</key>
-        <string>string.quoted.raw.single.python string.interpolated.python</string>
+        <string>string.interpolated.python string.quoted.raw.single.python</string>
         <key>match</key>
         <string>(?x)
   (.+?)
@@ -8177,7 +8177,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>storage.type.string.python string.quoted.multi.python string.interpolated.python</string>
+            <string>string.interpolated.python string.quoted.multi.python storage.type.string.python</string>
           </dict>
           <key>2</key>
           <dict>
@@ -8187,7 +8187,7 @@ indirectly through syntactic constructs
           <key>3</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python</string>
+            <string>punctuation.definition.string.begin.python string.interpolated.python string.quoted.multi.python</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -8195,7 +8195,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python</string>
+            <string>punctuation.definition.string.end.python string.interpolated.python string.quoted.multi.python</string>
           </dict>
           <key>2</key>
           <dict>
@@ -8241,12 +8241,12 @@ indirectly through syntactic constructs
           <key>2</key>
           <dict>
             <key>name</key>
-            <string>storage.type.string.python string.quoted.multi.python string.interpolated.python</string>
+            <string>string.interpolated.python string.quoted.multi.python storage.type.string.python</string>
           </dict>
           <key>3</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.multi.python punctuation.definition.string.begin.python</string>
+            <string>punctuation.definition.string.begin.python string.quoted.multi.python</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -8254,7 +8254,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python</string>
+            <string>punctuation.definition.string.end.python string.interpolated.python string.quoted.multi.python</string>
           </dict>
           <key>2</key>
           <dict>
@@ -8295,12 +8295,12 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>storage.type.string.python string.quoted.raw.multi.python string.interpolated.python</string>
+            <string>string.interpolated.python string.quoted.raw.multi.python storage.type.string.python</string>
           </dict>
           <key>2</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.raw.multi.python punctuation.definition.string.begin.python</string>
+            <string>punctuation.definition.string.begin.python string.quoted.raw.multi.python</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -8308,7 +8308,7 @@ indirectly through syntactic constructs
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>string.quoted.raw.multi.python string.interpolated.python punctuation.definition.string.end.python</string>
+            <string>punctuation.definition.string.end.python string.interpolated.python string.quoted.raw.multi.python</string>
           </dict>
           <key>2</key>
           <dict>
@@ -8339,7 +8339,7 @@ indirectly through syntactic constructs
       <key>fstring-multi-core</key>
       <dict>
         <key>name</key>
-        <string>string.quoted.multi.python string.interpolated.python</string>
+        <string>string.interpolated.python string.quoted.multi.python</string>
         <key>match</key>
         <string>(?x)
   (.+?)
@@ -8362,7 +8362,7 @@ indirectly through syntactic constructs
       <key>fstring-raw-multi-core</key>
       <dict>
         <key>name</key>
-        <string>string.quoted.raw.multi.python string.interpolated.python</string>
+        <string>string.interpolated.python string.quoted.raw.multi.python</string>
         <key>match</key>
         <string>(?x)
   (.+?)
diff --git a/grammars/MagicRegExp.tmLanguage b/grammars/MagicRegExp.tmLanguage
index 37c42d1b..3bc9d48e 100644
--- a/grammars/MagicRegExp.tmLanguage
+++ b/grammars/MagicRegExp.tmLanguage
@@ -148,7 +148,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.backreference.named.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.backreference.named.begin.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -158,7 +158,7 @@
           <key>3</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.backreference.named.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.backreference.named.end.regexp</string>
           </dict>
         </dict>
       </dict>
@@ -348,7 +348,7 @@
               <key>1</key>
               <dict>
                 <key>name</key>
-                <string>constant.other.set.regexp punctuation.character.set.begin.regexp</string>
+                <string>punctuation.character.set.begin.regexp constant.other.set.regexp</string>
               </dict>
               <key>2</key>
               <dict>
@@ -366,7 +366,7 @@
               <key>1</key>
               <dict>
                 <key>name</key>
-                <string>constant.other.set.regexp punctuation.character.set.end.regexp</string>
+                <string>punctuation.character.set.end.regexp constant.other.set.regexp</string>
               </dict>
               <key>2</key>
               <dict>
@@ -405,7 +405,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -418,7 +418,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -495,7 +495,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp</string>
+            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -535,7 +535,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp</string>
+            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -575,7 +575,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp</string>
+            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -615,7 +615,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp</string>
+            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -655,7 +655,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp</string>
+            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -682,7 +682,7 @@
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -690,7 +690,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>
@@ -717,7 +717,7 @@
           <key>0</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
           </dict>
         </dict>
         <key>endCaptures</key>
@@ -725,7 +725,7 @@
           <key>1</key>
           <dict>
             <key>name</key>
-            <string>punctuation.parenthesis.end.regexp support.other.parenthesis.regexp</string>
+            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
           </dict>
           <key>2</key>
           <dict>

From 69a736a9add58d8e8b252e7afa8dcb38d183c509 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 3 Feb 2017 20:41:04 -0500
Subject: [PATCH 06/65] Prepare 1.0.6 release

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index caf6f1ba..b525cf27 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "MagicPython",
-  "version": "1.0.5",
+  "version": "1.0.6",
   "engines": {
     "atom": "*",
     "node": "*",

From 18de6108ce2d2520c77958db312d31a78777139b Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 3 Feb 2017 20:45:14 -0500
Subject: [PATCH 07/65] Bump syntaxdev version to v0.0.13

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 3ecb8621..4062bca7 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ test: release
 		then echo "Error: package.version != git.tag" && exit 1 ; fi
 
 devenv:
-	npm install syntaxdev@0.0.12
+	npm install syntaxdev@0.0.13
 
 release:
 	./node_modules/.bin/syntaxdev build-plist --in grammars/src/MagicPython.syntax.yaml --out grammars/MagicPython.tmLanguage

From 1381f146dbea3afc934656f0d6a74e7e764f7d5c Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Thu, 23 Feb 2017 16:28:03 -0500
Subject: [PATCH 08/65] atom-sync: Match python shebang with trailing
 whitespace before path

---
 grammars/MagicPython.cson            | 4 ++--
 grammars/MagicPython.tmLanguage      | 4 ++--
 grammars/src/MagicPython.syntax.yaml | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 3f9fa44f..9d9c9185 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -16,8 +16,8 @@ fileTypes: [
   "gypi"
   "wsgi"
 ]
-first_line_match: "^#!/.*\\bpython[\\d\\.]*\\b"
-firstLineMatch: "^#!/.*\\bpython[\\d\\.]*\\b"
+first_line_match: "^#![ \\t]*/.*\\bpython[\\d\\.]*\\b"
+firstLineMatch: "^#![ \\t]*/.*\\bpython[\\d\\.]*\\b"
 uuid: "742deb57-6e38-4192-bed6-410746efd85d"
 patterns: [
   {
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index fe97f739..ccbc54d3 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -24,9 +24,9 @@
       <string>wsgi</string>
     </array>
     <key>first_line_match</key>
-    <string>^#!/.*\bpython[\d\.]*\b</string>
+    <string>^#![ \t]*/.*\bpython[\d\.]*\b</string>
     <key>firstLineMatch</key>
-    <string>^#!/.*\bpython[\d\.]*\b</string>
+    <string>^#![ \t]*/.*\bpython[\d\.]*\b</string>
     <key>uuid</key>
     <string>742deb57-6e38-4192-bed6-410746efd85d</string>
     <key>patterns</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 589f7741..5411bf30 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -5,8 +5,8 @@ scopeName: source.python
 fileTypes: [py, py3, rpy, pyw, cpy, pyi,
             SConstruct, Sconstruct, sconstruct, SConscript,
             gyp, gypi, wsgi]
-first_line_match: ^#!/.*\bpython[\d\.]*\b
-firstLineMatch: ^#!/.*\bpython[\d\.]*\b
+first_line_match: ^#![ \t]*/.*\bpython[\d\.]*\b
+firstLineMatch: ^#![ \t]*/.*\bpython[\d\.]*\b
 uuid: 742deb57-6e38-4192-bed6-410746efd85d
 
 patterns:

From 38a783c7ba62d58ec3c4b2e264ed4628eef8a0f7 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Thu, 23 Feb 2017 17:48:01 -0500
Subject: [PATCH 09/65] Generate Atom spec test files

---
 .travis.yml                      |     3 +-
 Makefile                         |    12 +-
 test/atom-spec/README.md         |     2 +
 test/atom-spec/basics-spec.js    |    25 +
 test/atom-spec/python-re-spec.js |   539 ++
 test/atom-spec/python-spec.js    | 14149 +++++++++++++++++++++++++++++
 6 files changed, 14726 insertions(+), 4 deletions(-)
 create mode 100644 test/atom-spec/README.md
 create mode 100644 test/atom-spec/basics-spec.js
 create mode 100644 test/atom-spec/python-re-spec.js
 create mode 100644 test/atom-spec/python-spec.js

diff --git a/.travis.yml b/.travis.yml
index 8df07568..100771e4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,4 +7,5 @@ install:
   - make
 
 script:
-  - make test
+  - make ci-test
+  - 'curl -s https://raw.githubusercontent.com/atom/ci/master/build-package.sh | sh'
diff --git a/Makefile b/Makefile
index 4062bca7..3a581363 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
-.PHONY: all test release devenv publish
+.PHONY: all ci-test test release devenv publish
 
 all: devenv release
 
-test: release
+ci-test: release
 #	Run tests
 	./node_modules/.bin/syntaxdev test --tests test/**/*.py --syntax grammars/src/MagicPython.syntax.yaml
 	./node_modules/.bin/syntaxdev test --tests test/**/*.re --syntax grammars/src/MagicRegExp.syntax.yaml
@@ -15,8 +15,11 @@ test: release
 	] ; \
 		then echo "Error: package.version != git.tag" && exit 1 ; fi
 
+test: ci-test
+	atom -t .
+
 devenv:
-	npm install syntaxdev@0.0.13
+	npm install syntaxdev@0.0.15
 
 release:
 	./node_modules/.bin/syntaxdev build-plist --in grammars/src/MagicPython.syntax.yaml --out grammars/MagicPython.tmLanguage
@@ -27,6 +30,9 @@ release:
 
 	./node_modules/.bin/syntaxdev scopes --syntax grammars/src/MagicPython.syntax.yaml > misc/scopes
 
+	./node_modules/.bin/syntaxdev atom-spec --package-name MagicPython --tests test/**/*.py --syntax grammars/src/MagicPython.syntax.yaml --out test/atom-spec/python-spec.js
+	./node_modules/.bin/syntaxdev atom-spec --package-name MagicPython --tests test/**/*.re --syntax grammars/src/MagicRegExp.syntax.yaml --out test/atom-spec/python-re-spec.js
+
 publish: test
 	apm publish patch
 	rm -rf ./node_modules/syntaxdev
diff --git a/test/atom-spec/README.md b/test/atom-spec/README.md
new file mode 100644
index 00000000..2708e928
--- /dev/null
+++ b/test/atom-spec/README.md
@@ -0,0 +1,2 @@
+This directory contains tests for Atom editor.  Spec files prefixed
+with `python-` are autogenerated by `make`.
diff --git a/test/atom-spec/basics-spec.js b/test/atom-spec/basics-spec.js
new file mode 100644
index 00000000..b8b35468
--- /dev/null
+++ b/test/atom-spec/basics-spec.js
@@ -0,0 +1,25 @@
+describe("MagicPython basic integration tests", function() {
+  var grammar = null;
+
+  beforeEach(function() {
+    waitsForPromise(function() {
+      return atom.packages.activatePackage("MagicPython")
+    });
+    runs(function() {
+      grammar = atom.grammars.grammarForScopeName("source.python")
+    });
+  });
+
+  it("recognises shebang on firstline", function() {
+    expect(grammar.firstLineRegex.scanner.findNextMatchSync(
+      "#!/usr/bin/env python")).not.toBeNull();
+
+    expect(grammar.firstLineRegex.scanner.findNextMatchSync(
+      "#! /usr/bin/env python")).not.toBeNull();
+  });
+
+  it("parses the grammar", function() {
+    expect(grammar).toBeDefined();
+    expect(grammar.scopeName).toBe("source.python");
+  });
+});
diff --git a/test/atom-spec/python-re-spec.js b/test/atom-spec/python-re-spec.js
new file mode 100644
index 00000000..5a5557c5
--- /dev/null
+++ b/test/atom-spec/python-re-spec.js
@@ -0,0 +1,539 @@
+// !!! autogenerated; do not edit !!!
+
+
+
+describe("Grammar Tests", function() {
+  var grammar = null;
+  beforeEach(function() {
+    waitsForPromise(function() {
+      return atom.packages.activatePackage("MagicPython")
+    });
+    runs(function() {
+      grammar = atom.grammars.grammarForScopeName("source.regexp.python")
+    });
+  });
+
+
+  it("test/regexp/comments1.re", 
+    function() {
+      tokens = grammar.tokenizeLines("foo(?#comment)bar")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][1].value).toBe("(?#");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","comment.regexp","punctuation.comment.begin.regexp"]);
+      expect(tokens[0][2].value).toBe("comment");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","comment.regexp"]);
+      expect(tokens[0][3].value).toBe(")");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python","comment.regexp","punctuation.comment.end.regexp"]);
+      expect(tokens[0][4].value).toBe("bar");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python"]);
+    });
+
+  it("test/regexp/comments2.re", 
+    function() {
+      tokens = grammar.tokenizeLines("(?x)\n    foo     (?#\ncomment 1\n            ) bar\n    baz     (?#comment 2)")
+      expect(tokens[0][0].value).toBe("(?x)");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","storage.modifier.flag.regexp"]);
+      expect(tokens[1][0].value).toBe("    foo     ");
+      expect(tokens[1][0].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[1][1].value).toBe("(?#");
+      expect(tokens[1][1].scopes).toEqual(["source.regexp.python","comment.regexp","punctuation.comment.begin.regexp"]);
+      expect(tokens[2][0].value).toBe("comment 1");
+      expect(tokens[2][0].scopes).toEqual(["source.regexp.python","comment.regexp"]);
+      expect(tokens[3][0].value).toBe("            ");
+      expect(tokens[3][0].scopes).toEqual(["source.regexp.python","comment.regexp"]);
+      expect(tokens[3][1].value).toBe(")");
+      expect(tokens[3][1].scopes).toEqual(["source.regexp.python","comment.regexp","punctuation.comment.end.regexp"]);
+      expect(tokens[3][2].value).toBe(" bar");
+      expect(tokens[3][2].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[4][0].value).toBe("    baz     ");
+      expect(tokens[4][0].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[4][1].value).toBe("(?#");
+      expect(tokens[4][1].scopes).toEqual(["source.regexp.python","comment.regexp","punctuation.comment.begin.regexp"]);
+      expect(tokens[4][2].value).toBe("comment 2");
+      expect(tokens[4][2].scopes).toEqual(["source.regexp.python","comment.regexp"]);
+      expect(tokens[4][3].value).toBe(")");
+      expect(tokens[4][3].scopes).toEqual(["source.regexp.python","comment.regexp","punctuation.comment.end.regexp"]);
+    });
+
+  it("test/regexp/conditional1.re", 
+    function() {
+      tokens = grammar.tokenizeLines("(<)?(\\w+@\\w+(?:\\.\\w+)+)(?(1)>|$)")
+      expect(tokens[0][0].value).toBe("(");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[0][1].value).toBe("<");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][2].value).toBe(")");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[0][3].value).toBe("?");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][4].value).toBe("(");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[0][5].value).toBe("\\w");
+      expect(tokens[0][5].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][6].value).toBe("+");
+      expect(tokens[0][6].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][7].value).toBe("@");
+      expect(tokens[0][7].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][8].value).toBe("\\w");
+      expect(tokens[0][8].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][9].value).toBe("+");
+      expect(tokens[0][9].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][10].value).toBe("(?:");
+      expect(tokens[0][10].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[0][11].value).toBe("\\.");
+      expect(tokens[0][11].scopes).toEqual(["source.regexp.python","constant.character.escape.regexp"]);
+      expect(tokens[0][12].value).toBe("\\w");
+      expect(tokens[0][12].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][13].value).toBe("+");
+      expect(tokens[0][13].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][14].value).toBe(")");
+      expect(tokens[0][14].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[0][15].value).toBe("+");
+      expect(tokens[0][15].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][16].value).toBe(")");
+      expect(tokens[0][16].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[0][17].value).toBe("(");
+      expect(tokens[0][17].scopes).toEqual(["source.regexp.python","keyword.operator.conditional.regexp","punctuation.parenthesis.conditional.begin.regexp"]);
+      expect(tokens[0][18].value).toBe("?(1)");
+      expect(tokens[0][18].scopes).toEqual(["source.regexp.python","keyword.operator.conditional.regexp"]);
+      expect(tokens[0][19].value).toBe(">");
+      expect(tokens[0][19].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][20].value).toBe("|");
+      expect(tokens[0][20].scopes).toEqual(["source.regexp.python","keyword.operator.disjunction.regexp"]);
+      expect(tokens[0][21].value).toBe("$");
+      expect(tokens[0][21].scopes).toEqual(["source.regexp.python","support.other.match.end.regexp"]);
+      expect(tokens[0][22].value).toBe(")");
+      expect(tokens[0][22].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp"]);
+    });
+
+  it("test/regexp/escaping1.re", 
+    function() {
+      tokens = grammar.tokenizeLines("foo\\\nbar")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][1].value).toBe("\\");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","constant.character.escape.regexp"]);
+      expect(tokens[1][0].value).toBe("bar");
+      expect(tokens[1][0].scopes).toEqual(["source.regexp.python"]);
+    });
+
+  it("test/regexp/escaping2.re", 
+    function() {
+      tokens = grammar.tokenizeLines("start\\A\\b\\B\\d\\D\\s\\S\\w\\W\\Z\\\\\\1\\01\\1111\\0011\\xfab\\u123fb\\U1234aaaab\\c")
+      expect(tokens[0][0].value).toBe("start");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][1].value).toBe("\\A");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][2].value).toBe("\\b");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][3].value).toBe("\\B");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][4].value).toBe("\\d");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][5].value).toBe("\\D");
+      expect(tokens[0][5].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][6].value).toBe("\\s");
+      expect(tokens[0][6].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][7].value).toBe("\\S");
+      expect(tokens[0][7].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][8].value).toBe("\\w");
+      expect(tokens[0][8].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][9].value).toBe("\\W");
+      expect(tokens[0][9].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][10].value).toBe("\\Z");
+      expect(tokens[0][10].scopes).toEqual(["source.regexp.python","support.other.escape.special.regexp"]);
+      expect(tokens[0][11].value).toBe("\\\\");
+      expect(tokens[0][11].scopes).toEqual(["source.regexp.python","constant.character.escape.regexp"]);
+      expect(tokens[0][12].value).toBe("\\1");
+      expect(tokens[0][12].scopes).toEqual(["source.regexp.python","meta.backreference.regexp","entity.name.tag.backreference.regexp"]);
+      expect(tokens[0][13].value).toBe("\\01");
+      expect(tokens[0][13].scopes).toEqual(["source.regexp.python","constant.character.escape.regexp"]);
+      expect(tokens[0][14].value).toBe("\\111");
+      expect(tokens[0][14].scopes).toEqual(["source.regexp.python","constant.character.escape.regexp"]);
+      expect(tokens[0][15].value).toBe("1");
+      expect(tokens[0][15].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][16].value).toBe("\\001");
+      expect(tokens[0][16].scopes).toEqual(["source.regexp.python","constant.character.escape.regexp"]);
+      expect(tokens[0][17].value).toBe("1");
+      expect(tokens[0][17].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][18].value).toBe("\\xfa");
+      expect(tokens[0][18].scopes).toEqual(["source.regexp.python","constant.character.escape.regexp"]);
+      expect(tokens[0][19].value).toBe("b");
+      expect(tokens[0][19].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][20].value).toBe("\\u123f");
+      expect(tokens[0][20].scopes).toEqual(["source.regexp.python","constant.character.unicode.regexp"]);
+      expect(tokens[0][21].value).toBe("b");
+      expect(tokens[0][21].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][22].value).toBe("\\U1234aaaa");
+      expect(tokens[0][22].scopes).toEqual(["source.regexp.python","constant.character.unicode.regexp"]);
+      expect(tokens[0][23].value).toBe("b");
+      expect(tokens[0][23].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][24].value).toBe("\\c");
+      expect(tokens[0][24].scopes).toEqual(["source.regexp.python","constant.character.escape.regexp"]);
+    });
+
+  it("test/regexp/escaping3.re", 
+    function() {
+      tokens = grammar.tokenizeLines("[start\\A\\b\\B\\d\\D\\s\\S\\w\\W\\Z\\\\\\1\\01\\1111\\0011\\xfab\\u123fb\\U1234aaaab\\c]")
+      expect(tokens[0][0].value).toBe("[");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[0][1].value).toBe("s");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][2].value).toBe("t");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][3].value).toBe("a");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][5].value).toBe("t");
+      expect(tokens[0][5].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][6].value).toBe("\\A");
+      expect(tokens[0][6].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[0][7].value).toBe("\\b");
+      expect(tokens[0][7].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][8].value).toBe("\\B");
+      expect(tokens[0][8].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[0][9].value).toBe("\\d");
+      expect(tokens[0][9].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[0][10].value).toBe("\\D");
+      expect(tokens[0][10].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[0][11].value).toBe("\\s");
+      expect(tokens[0][11].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[0][12].value).toBe("\\S");
+      expect(tokens[0][12].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[0][13].value).toBe("\\w");
+      expect(tokens[0][13].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[0][14].value).toBe("\\W");
+      expect(tokens[0][14].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[0][15].value).toBe("\\Z");
+      expect(tokens[0][15].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[0][16].value).toBe("\\\\");
+      expect(tokens[0][16].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][17].value).toBe("\\1");
+      expect(tokens[0][17].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][18].value).toBe("\\01");
+      expect(tokens[0][18].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][19].value).toBe("\\111");
+      expect(tokens[0][19].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][20].value).toBe("1");
+      expect(tokens[0][20].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][21].value).toBe("\\001");
+      expect(tokens[0][21].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][22].value).toBe("1");
+      expect(tokens[0][22].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][23].value).toBe("\\xfa");
+      expect(tokens[0][23].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][24].value).toBe("b");
+      expect(tokens[0][24].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][25].value).toBe("\\u123f");
+      expect(tokens[0][25].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.unicode.regexp"]);
+      expect(tokens[0][26].value).toBe("b");
+      expect(tokens[0][26].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][27].value).toBe("\\U1234aaaa");
+      expect(tokens[0][27].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.unicode.regexp"]);
+      expect(tokens[0][28].value).toBe("b");
+      expect(tokens[0][28].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][29].value).toBe("\\c");
+      expect(tokens[0][29].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][30].value).toBe("]");
+      expect(tokens[0][30].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+    });
+
+  it("test/regexp/escaping4.re", 
+    function() {
+      tokens = grammar.tokenizeLines("[start\\a\\b\\c\\d\\f\\n\\r\\t\\v]")
+      expect(tokens[0][0].value).toBe("[");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[0][1].value).toBe("s");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][2].value).toBe("t");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][3].value).toBe("a");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][5].value).toBe("t");
+      expect(tokens[0][5].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][6].value).toBe("\\a");
+      expect(tokens[0][6].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][7].value).toBe("\\b");
+      expect(tokens[0][7].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][8].value).toBe("\\c");
+      expect(tokens[0][8].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][9].value).toBe("\\d");
+      expect(tokens[0][9].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[0][10].value).toBe("\\f");
+      expect(tokens[0][10].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][11].value).toBe("\\n");
+      expect(tokens[0][11].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][12].value).toBe("\\r");
+      expect(tokens[0][12].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][13].value).toBe("\\t");
+      expect(tokens[0][13].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][14].value).toBe("\\v");
+      expect(tokens[0][14].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][15].value).toBe("]");
+      expect(tokens[0][15].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+    });
+
+  it("test/regexp/flags1.re", 
+    function() {
+      tokens = grammar.tokenizeLines("(?aiLmsux)foo")
+      expect(tokens[0][0].value).toBe("(?aiLmsux)");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","storage.modifier.flag.regexp"]);
+      expect(tokens[0][1].value).toBe("foo");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python"]);
+    });
+
+  it("test/regexp/group1.re", 
+    function() {
+      tokens = grammar.tokenizeLines("(?x)\n    (?:not) (foo)\n        .* (?P<bar>BAR)\n    \\1 (?P=bar)")
+      expect(tokens[0][0].value).toBe("(?x)");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","storage.modifier.flag.regexp"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[1][1].value).toBe("(?:");
+      expect(tokens[1][1].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[1][2].value).toBe("not");
+      expect(tokens[1][2].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[1][3].value).toBe(")");
+      expect(tokens[1][3].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[1][4].value).toBe(" ");
+      expect(tokens[1][4].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[1][5].value).toBe("(");
+      expect(tokens[1][5].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[1][6].value).toBe("foo");
+      expect(tokens[1][6].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[1][7].value).toBe(")");
+      expect(tokens[1][7].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[2][0].value).toBe("        ");
+      expect(tokens[2][0].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[2][1].value).toBe(".");
+      expect(tokens[2][1].scopes).toEqual(["source.regexp.python","support.other.match.any.regexp"]);
+      expect(tokens[2][2].value).toBe("*");
+      expect(tokens[2][2].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[2][4].value).toBe("(");
+      expect(tokens[2][4].scopes).toEqual(["source.regexp.python","meta.named.regexp","punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[2][5].value).toBe("?P<bar>");
+      expect(tokens[2][5].scopes).toEqual(["source.regexp.python","meta.named.regexp","entity.name.tag.named.group.regexp"]);
+      expect(tokens[2][6].value).toBe("BAR");
+      expect(tokens[2][6].scopes).toEqual(["source.regexp.python","meta.named.regexp"]);
+      expect(tokens[2][7].value).toBe(")");
+      expect(tokens[2][7].scopes).toEqual(["source.regexp.python","meta.named.regexp","punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[3][1].value).toBe("\\1");
+      expect(tokens[3][1].scopes).toEqual(["source.regexp.python","meta.backreference.regexp","entity.name.tag.backreference.regexp"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[3][3].value).toBe("(");
+      expect(tokens[3][3].scopes).toEqual(["source.regexp.python","meta.backreference.named.regexp","punctuation.parenthesis.backreference.named.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[3][4].value).toBe("?P=bar");
+      expect(tokens[3][4].scopes).toEqual(["source.regexp.python","meta.backreference.named.regexp","entity.name.tag.named.backreference.regexp"]);
+      expect(tokens[3][5].value).toBe(")");
+      expect(tokens[3][5].scopes).toEqual(["source.regexp.python","meta.backreference.named.regexp","punctuation.parenthesis.backreference.named.end.regexp support.other.parenthesis.regexp"]);
+    });
+
+  it("test/regexp/lookahead1.re", 
+    function() {
+      tokens = grammar.tokenizeLines("foo(?=bar)")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","keyword.operator.lookahead.regexp","punctuation.parenthesis.lookahead.begin.regexp"]);
+      expect(tokens[0][2].value).toBe("?=");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","keyword.operator.lookahead.regexp"]);
+      expect(tokens[0][3].value).toBe("bar");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp"]);
+    });
+
+  it("test/regexp/lookahead2.re", 
+    function() {
+      tokens = grammar.tokenizeLines("foo(?!bar)")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","keyword.operator.lookahead.negative.regexp","punctuation.parenthesis.lookahead.begin.regexp"]);
+      expect(tokens[0][2].value).toBe("?!");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","keyword.operator.lookahead.negative.regexp"]);
+      expect(tokens[0][3].value).toBe("bar");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp"]);
+    });
+
+  it("test/regexp/lookbehind1.re", 
+    function() {
+      tokens = grammar.tokenizeLines("(?<=foo)bar")
+      expect(tokens[0][0].value).toBe("(");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","keyword.operator.lookbehind.regexp","punctuation.parenthesis.lookbehind.begin.regexp"]);
+      expect(tokens[0][1].value).toBe("?<=");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","keyword.operator.lookbehind.regexp"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][3].value).toBe(")");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp"]);
+      expect(tokens[0][4].value).toBe("bar");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python"]);
+    });
+
+  it("test/regexp/lookbehind2.re", 
+    function() {
+      tokens = grammar.tokenizeLines("(?<!foo)bar")
+      expect(tokens[0][0].value).toBe("(");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","keyword.operator.lookbehind.negative.regexp","punctuation.parenthesis.lookbehind.begin.regexp"]);
+      expect(tokens[0][1].value).toBe("?<!");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","keyword.operator.lookbehind.negative.regexp"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][3].value).toBe(")");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python","punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp"]);
+      expect(tokens[0][4].value).toBe("bar");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python"]);
+    });
+
+  it("test/regexp/quantifiers1.re", 
+    function() {
+      tokens = grammar.tokenizeLines("^a+b*c?d*?e+?f??$")
+      expect(tokens[0][0].value).toBe("^");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","support.other.match.begin.regexp"]);
+      expect(tokens[0][1].value).toBe("a");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][2].value).toBe("+");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][3].value).toBe("b");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][4].value).toBe("*");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][5].value).toBe("c");
+      expect(tokens[0][5].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][6].value).toBe("?");
+      expect(tokens[0][6].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][7].value).toBe("d");
+      expect(tokens[0][7].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][8].value).toBe("*?");
+      expect(tokens[0][8].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][9].value).toBe("e");
+      expect(tokens[0][9].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][10].value).toBe("+?");
+      expect(tokens[0][10].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][11].value).toBe("f");
+      expect(tokens[0][11].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][12].value).toBe("??");
+      expect(tokens[0][12].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][13].value).toBe("$");
+      expect(tokens[0][13].scopes).toEqual(["source.regexp.python","support.other.match.end.regexp"]);
+    });
+
+  it("test/regexp/quantifiers2.re", 
+    function() {
+      tokens = grammar.tokenizeLines("^a{10}b{,10}c{10,}d{10,100}$")
+      expect(tokens[0][0].value).toBe("^");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","support.other.match.begin.regexp"]);
+      expect(tokens[0][1].value).toBe("a");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][2].value).toBe("{10}");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][3].value).toBe("b");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][4].value).toBe("{,10}");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][5].value).toBe("c");
+      expect(tokens[0][5].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][6].value).toBe("{10,}");
+      expect(tokens[0][6].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][7].value).toBe("d");
+      expect(tokens[0][7].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][8].value).toBe("{10,100}");
+      expect(tokens[0][8].scopes).toEqual(["source.regexp.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][9].value).toBe("$");
+      expect(tokens[0][9].scopes).toEqual(["source.regexp.python","support.other.match.end.regexp"]);
+    });
+
+  it("test/regexp/set1.re", 
+    function() {
+      tokens = grammar.tokenizeLines("[]]")
+      expect(tokens[0][0].value).toBe("[");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[0][1].value).toBe("]");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][2].value).toBe("]");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+    });
+
+  it("test/regexp/set2.re", 
+    function() {
+      tokens = grammar.tokenizeLines("[^]]")
+      expect(tokens[0][0].value).toBe("[");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[0][1].value).toBe("^");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","keyword.operator.negation.regexp"]);
+      expect(tokens[0][2].value).toBe("]");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][3].value).toBe("]");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+    });
+
+  it("test/regexp/set3.re", 
+    function() {
+      tokens = grammar.tokenizeLines("[][(){}|*+?.\\]\\\\]")
+      expect(tokens[0][0].value).toBe("[");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[0][1].value).toBe("]");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][2].value).toBe("[");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][5].value).toBe("{");
+      expect(tokens[0][5].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][6].value).toBe("}");
+      expect(tokens[0][6].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][7].value).toBe("|");
+      expect(tokens[0][7].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][8].value).toBe("*");
+      expect(tokens[0][8].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][9].value).toBe("+");
+      expect(tokens[0][9].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][10].value).toBe("?");
+      expect(tokens[0][10].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][11].value).toBe(".");
+      expect(tokens[0][11].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][12].value).toBe("\\]");
+      expect(tokens[0][12].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][13].value).toBe("\\\\");
+      expect(tokens[0][13].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[0][14].value).toBe("]");
+      expect(tokens[0][14].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+    });
+
+  it("test/regexp/set4.re", 
+    function() {
+      tokens = grammar.tokenizeLines("^[^^]")
+      expect(tokens[0][0].value).toBe("^");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python","support.other.match.begin.regexp"]);
+      expect(tokens[0][1].value).toBe("[");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[0][2].value).toBe("^");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","keyword.operator.negation.regexp"]);
+      expect(tokens[0][3].value).toBe("^");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][4].value).toBe("]");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+    });
+
+  it("test/regexp/trivial.re", 
+    function() {
+      tokens = grammar.tokenizeLines("trivial")
+      expect(tokens[0][0].value).toBe("trivial");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python"]);
+    });
+});
+
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
new file mode 100644
index 00000000..4fa5f031
--- /dev/null
+++ b/test/atom-spec/python-spec.js
@@ -0,0 +1,14149 @@
+// !!! autogenerated; do not edit !!!
+
+
+
+describe("Grammar Tests", function() {
+  var grammar = null;
+  beforeEach(function() {
+    waitsForPromise(function() {
+      return atom.packages.activatePackage("MagicPython")
+    });
+    runs(function() {
+      grammar = atom.grammars.grammarForScopeName("source.python")
+    });
+  });
+
+
+  it("test/builtins/builtins1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("AttributeError ConnectionAbortedError\nPendingDeprecationWarning\nModuleNotFoundError\nSystemExit\nNotImplemented True None False Ellipsis\nWarning\nException BaseException\nsum oct abs type object print")
+      expect(tokens[0][0].value).toBe("AttributeError");
+      expect(tokens[0][0].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("ConnectionAbortedError");
+      expect(tokens[0][2].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[1][0].value).toBe("PendingDeprecationWarning");
+      expect(tokens[1][0].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[2][0].value).toBe("ModuleNotFoundError");
+      expect(tokens[2][0].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[3][0].value).toBe("SystemExit");
+      expect(tokens[3][0].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[4][0].value).toBe("NotImplemented");
+      expect(tokens[4][0].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("True");
+      expect(tokens[4][2].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[4][3].value).toBe(" ");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe("None");
+      expect(tokens[4][4].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[4][5].value).toBe(" ");
+      expect(tokens[4][5].scopes).toEqual(["source.python"]);
+      expect(tokens[4][6].value).toBe("False");
+      expect(tokens[4][6].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[4][7].value).toBe(" ");
+      expect(tokens[4][7].scopes).toEqual(["source.python"]);
+      expect(tokens[4][8].value).toBe("Ellipsis");
+      expect(tokens[4][8].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[5][0].value).toBe("Warning");
+      expect(tokens[5][0].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[6][0].value).toBe("Exception");
+      expect(tokens[6][0].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].value).toBe("BaseException");
+      expect(tokens[6][2].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[7][0].value).toBe("sum");
+      expect(tokens[7][0].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[7][1].value).toBe(" ");
+      expect(tokens[7][1].scopes).toEqual(["source.python"]);
+      expect(tokens[7][2].value).toBe("oct");
+      expect(tokens[7][2].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[7][3].value).toBe(" ");
+      expect(tokens[7][3].scopes).toEqual(["source.python"]);
+      expect(tokens[7][4].value).toBe("abs");
+      expect(tokens[7][4].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[7][5].value).toBe(" ");
+      expect(tokens[7][5].scopes).toEqual(["source.python"]);
+      expect(tokens[7][6].value).toBe("type");
+      expect(tokens[7][6].scopes).toEqual(["source.python","support.type.python"]);
+      expect(tokens[7][7].value).toBe(" ");
+      expect(tokens[7][7].scopes).toEqual(["source.python"]);
+      expect(tokens[7][8].value).toBe("object");
+      expect(tokens[7][8].scopes).toEqual(["source.python","support.type.python"]);
+      expect(tokens[7][9].value).toBe(" ");
+      expect(tokens[7][9].scopes).toEqual(["source.python"]);
+      expect(tokens[7][10].value).toBe("print");
+      expect(tokens[7][10].scopes).toEqual(["source.python","support.function.builtin.python"]);
+    });
+
+  it("test/builtins/builtins2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("Error\nfile reduce intern raw_input unicode cmp basestring execfile long xrange apply")
+      expect(tokens[0][0].value).toBe("Error");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("file");
+      expect(tokens[1][0].scopes).toEqual(["source.python","variable.legacy.builtin.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("reduce");
+      expect(tokens[1][2].scopes).toEqual(["source.python","variable.legacy.builtin.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("intern");
+      expect(tokens[1][4].scopes).toEqual(["source.python","variable.legacy.builtin.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("raw_input");
+      expect(tokens[1][6].scopes).toEqual(["source.python","variable.legacy.builtin.python"]);
+      expect(tokens[1][7].value).toBe(" ");
+      expect(tokens[1][7].scopes).toEqual(["source.python"]);
+      expect(tokens[1][8].value).toBe("unicode");
+      expect(tokens[1][8].scopes).toEqual(["source.python","variable.legacy.builtin.python"]);
+      expect(tokens[1][9].value).toBe(" ");
+      expect(tokens[1][9].scopes).toEqual(["source.python"]);
+      expect(tokens[1][10].value).toBe("cmp");
+      expect(tokens[1][10].scopes).toEqual(["source.python","variable.legacy.builtin.python"]);
+      expect(tokens[1][11].value).toBe(" ");
+      expect(tokens[1][11].scopes).toEqual(["source.python"]);
+      expect(tokens[1][12].value).toBe("basestring");
+      expect(tokens[1][12].scopes).toEqual(["source.python","variable.legacy.builtin.python"]);
+      expect(tokens[1][13].value).toBe(" ");
+      expect(tokens[1][13].scopes).toEqual(["source.python"]);
+      expect(tokens[1][14].value).toBe("execfile");
+      expect(tokens[1][14].scopes).toEqual(["source.python","variable.legacy.builtin.python"]);
+      expect(tokens[1][15].value).toBe(" ");
+      expect(tokens[1][15].scopes).toEqual(["source.python"]);
+      expect(tokens[1][16].value).toBe("long");
+      expect(tokens[1][16].scopes).toEqual(["source.python","variable.legacy.builtin.python"]);
+      expect(tokens[1][17].value).toBe(" ");
+      expect(tokens[1][17].scopes).toEqual(["source.python"]);
+      expect(tokens[1][18].value).toBe("xrange");
+      expect(tokens[1][18].scopes).toEqual(["source.python","variable.legacy.builtin.python"]);
+      expect(tokens[1][19].value).toBe(" ");
+      expect(tokens[1][19].scopes).toEqual(["source.python"]);
+      expect(tokens[1][20].value).toBe("apply");
+      expect(tokens[1][20].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/builtins/builtins3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("__all__ = ['bar', 'baz']\nsome.__bases__\nsome.__class__\nassert __debug__\n__builtins__\n__builtins__.len\nprint(__builtins__)\nsome.__dict__\nsome.__doc__\nsome.__file__\nsome.__members__\nsome.__metaclass__\nsome.__methods__\nsome.__module__\nsome.__mro__\nsome.__name__\nsome.__slots__\nsome.__subclasses__\nsome.__version__\nsome.__weakref__\nsome.__qualname__\nsome.__code__\nsome.__wrapped__\nsome.__signature__\nsome.__defaults__\nsome.__func__\nsome.__self__\nsome.__kwdefaults__\nsome.__matmul__\nsome.__imatmul__\nsome.__rmatmul__\nsome.__annotations__\nsome.__init_subclass__\nsome.__set_name__\nsome.__fspath__\nsome.__classcell__\nsome.__bytes__\nsome.__spec__\nsome.__path__\nsome.__prepare__\nsome.__package__\nsome.__notspecial__")
+      expect(tokens[0][0].value).toBe("__all__");
+      expect(tokens[0][0].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("[");
+      expect(tokens[0][4].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("bar");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][8].value).toBe(",");
+      expect(tokens[0][8].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("'");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][11].value).toBe("baz");
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][12].value).toBe("'");
+      expect(tokens[0][12].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][13].value).toBe("]");
+      expect(tokens[0][13].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[1][0].value).toBe("some");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(".");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("__bases__");
+      expect(tokens[1][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[2][0].value).toBe("some");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(".");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("__class__");
+      expect(tokens[2][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[3][0].value).toBe("assert");
+      expect(tokens[3][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("__debug__");
+      expect(tokens[3][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[4][0].value).toBe("__builtins__");
+      expect(tokens[4][0].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[5][0].value).toBe("__builtins__");
+      expect(tokens[5][0].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[5][1].value).toBe(".");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("len");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("print");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[6][1].value).toBe("(");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[6][2].value).toBe("__builtins__");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","support.variable.magic.python"]);
+      expect(tokens[6][3].value).toBe(")");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[7][0].value).toBe("some");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe(".");
+      expect(tokens[7][1].scopes).toEqual(["source.python"]);
+      expect(tokens[7][2].value).toBe("__dict__");
+      expect(tokens[7][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[8][0].value).toBe("some");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe(".");
+      expect(tokens[8][1].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].value).toBe("__doc__");
+      expect(tokens[8][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[9][0].value).toBe("some");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].value).toBe(".");
+      expect(tokens[9][1].scopes).toEqual(["source.python"]);
+      expect(tokens[9][2].value).toBe("__file__");
+      expect(tokens[9][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[10][0].value).toBe("some");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe(".");
+      expect(tokens[10][1].scopes).toEqual(["source.python"]);
+      expect(tokens[10][2].value).toBe("__members__");
+      expect(tokens[10][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[11][0].value).toBe("some");
+      expect(tokens[11][0].scopes).toEqual(["source.python"]);
+      expect(tokens[11][1].value).toBe(".");
+      expect(tokens[11][1].scopes).toEqual(["source.python"]);
+      expect(tokens[11][2].value).toBe("__metaclass__");
+      expect(tokens[11][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[12][0].value).toBe("some");
+      expect(tokens[12][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][1].value).toBe(".");
+      expect(tokens[12][1].scopes).toEqual(["source.python"]);
+      expect(tokens[12][2].value).toBe("__methods__");
+      expect(tokens[12][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[13][0].value).toBe("some");
+      expect(tokens[13][0].scopes).toEqual(["source.python"]);
+      expect(tokens[13][1].value).toBe(".");
+      expect(tokens[13][1].scopes).toEqual(["source.python"]);
+      expect(tokens[13][2].value).toBe("__module__");
+      expect(tokens[13][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[14][0].value).toBe("some");
+      expect(tokens[14][0].scopes).toEqual(["source.python"]);
+      expect(tokens[14][1].value).toBe(".");
+      expect(tokens[14][1].scopes).toEqual(["source.python"]);
+      expect(tokens[14][2].value).toBe("__mro__");
+      expect(tokens[14][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[15][0].value).toBe("some");
+      expect(tokens[15][0].scopes).toEqual(["source.python"]);
+      expect(tokens[15][1].value).toBe(".");
+      expect(tokens[15][1].scopes).toEqual(["source.python"]);
+      expect(tokens[15][2].value).toBe("__name__");
+      expect(tokens[15][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[16][0].value).toBe("some");
+      expect(tokens[16][0].scopes).toEqual(["source.python"]);
+      expect(tokens[16][1].value).toBe(".");
+      expect(tokens[16][1].scopes).toEqual(["source.python"]);
+      expect(tokens[16][2].value).toBe("__slots__");
+      expect(tokens[16][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[17][0].value).toBe("some");
+      expect(tokens[17][0].scopes).toEqual(["source.python"]);
+      expect(tokens[17][1].value).toBe(".");
+      expect(tokens[17][1].scopes).toEqual(["source.python"]);
+      expect(tokens[17][2].value).toBe("__subclasses__");
+      expect(tokens[17][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[18][0].value).toBe("some");
+      expect(tokens[18][0].scopes).toEqual(["source.python"]);
+      expect(tokens[18][1].value).toBe(".");
+      expect(tokens[18][1].scopes).toEqual(["source.python"]);
+      expect(tokens[18][2].value).toBe("__version__");
+      expect(tokens[18][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[19][0].value).toBe("some");
+      expect(tokens[19][0].scopes).toEqual(["source.python"]);
+      expect(tokens[19][1].value).toBe(".");
+      expect(tokens[19][1].scopes).toEqual(["source.python"]);
+      expect(tokens[19][2].value).toBe("__weakref__");
+      expect(tokens[19][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[20][0].value).toBe("some");
+      expect(tokens[20][0].scopes).toEqual(["source.python"]);
+      expect(tokens[20][1].value).toBe(".");
+      expect(tokens[20][1].scopes).toEqual(["source.python"]);
+      expect(tokens[20][2].value).toBe("__qualname__");
+      expect(tokens[20][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[21][0].value).toBe("some");
+      expect(tokens[21][0].scopes).toEqual(["source.python"]);
+      expect(tokens[21][1].value).toBe(".");
+      expect(tokens[21][1].scopes).toEqual(["source.python"]);
+      expect(tokens[21][2].value).toBe("__code__");
+      expect(tokens[21][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[22][0].value).toBe("some");
+      expect(tokens[22][0].scopes).toEqual(["source.python"]);
+      expect(tokens[22][1].value).toBe(".");
+      expect(tokens[22][1].scopes).toEqual(["source.python"]);
+      expect(tokens[22][2].value).toBe("__wrapped__");
+      expect(tokens[22][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[23][0].value).toBe("some");
+      expect(tokens[23][0].scopes).toEqual(["source.python"]);
+      expect(tokens[23][1].value).toBe(".");
+      expect(tokens[23][1].scopes).toEqual(["source.python"]);
+      expect(tokens[23][2].value).toBe("__signature__");
+      expect(tokens[23][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[24][0].value).toBe("some");
+      expect(tokens[24][0].scopes).toEqual(["source.python"]);
+      expect(tokens[24][1].value).toBe(".");
+      expect(tokens[24][1].scopes).toEqual(["source.python"]);
+      expect(tokens[24][2].value).toBe("__defaults__");
+      expect(tokens[24][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[25][0].value).toBe("some");
+      expect(tokens[25][0].scopes).toEqual(["source.python"]);
+      expect(tokens[25][1].value).toBe(".");
+      expect(tokens[25][1].scopes).toEqual(["source.python"]);
+      expect(tokens[25][2].value).toBe("__func__");
+      expect(tokens[25][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[26][0].value).toBe("some");
+      expect(tokens[26][0].scopes).toEqual(["source.python"]);
+      expect(tokens[26][1].value).toBe(".");
+      expect(tokens[26][1].scopes).toEqual(["source.python"]);
+      expect(tokens[26][2].value).toBe("__self__");
+      expect(tokens[26][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[27][0].value).toBe("some");
+      expect(tokens[27][0].scopes).toEqual(["source.python"]);
+      expect(tokens[27][1].value).toBe(".");
+      expect(tokens[27][1].scopes).toEqual(["source.python"]);
+      expect(tokens[27][2].value).toBe("__kwdefaults__");
+      expect(tokens[27][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[28][0].value).toBe("some");
+      expect(tokens[28][0].scopes).toEqual(["source.python"]);
+      expect(tokens[28][1].value).toBe(".");
+      expect(tokens[28][1].scopes).toEqual(["source.python"]);
+      expect(tokens[28][2].value).toBe("__matmul__");
+      expect(tokens[28][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[29][0].value).toBe("some");
+      expect(tokens[29][0].scopes).toEqual(["source.python"]);
+      expect(tokens[29][1].value).toBe(".");
+      expect(tokens[29][1].scopes).toEqual(["source.python"]);
+      expect(tokens[29][2].value).toBe("__imatmul__");
+      expect(tokens[29][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[30][0].value).toBe("some");
+      expect(tokens[30][0].scopes).toEqual(["source.python"]);
+      expect(tokens[30][1].value).toBe(".");
+      expect(tokens[30][1].scopes).toEqual(["source.python"]);
+      expect(tokens[30][2].value).toBe("__rmatmul__");
+      expect(tokens[30][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[31][0].value).toBe("some");
+      expect(tokens[31][0].scopes).toEqual(["source.python"]);
+      expect(tokens[31][1].value).toBe(".");
+      expect(tokens[31][1].scopes).toEqual(["source.python"]);
+      expect(tokens[31][2].value).toBe("__annotations__");
+      expect(tokens[31][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[32][0].value).toBe("some");
+      expect(tokens[32][0].scopes).toEqual(["source.python"]);
+      expect(tokens[32][1].value).toBe(".");
+      expect(tokens[32][1].scopes).toEqual(["source.python"]);
+      expect(tokens[32][2].value).toBe("__init_subclass__");
+      expect(tokens[32][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[33][0].value).toBe("some");
+      expect(tokens[33][0].scopes).toEqual(["source.python"]);
+      expect(tokens[33][1].value).toBe(".");
+      expect(tokens[33][1].scopes).toEqual(["source.python"]);
+      expect(tokens[33][2].value).toBe("__set_name__");
+      expect(tokens[33][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[34][0].value).toBe("some");
+      expect(tokens[34][0].scopes).toEqual(["source.python"]);
+      expect(tokens[34][1].value).toBe(".");
+      expect(tokens[34][1].scopes).toEqual(["source.python"]);
+      expect(tokens[34][2].value).toBe("__fspath__");
+      expect(tokens[34][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[35][0].value).toBe("some");
+      expect(tokens[35][0].scopes).toEqual(["source.python"]);
+      expect(tokens[35][1].value).toBe(".");
+      expect(tokens[35][1].scopes).toEqual(["source.python"]);
+      expect(tokens[35][2].value).toBe("__classcell__");
+      expect(tokens[35][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[36][0].value).toBe("some");
+      expect(tokens[36][0].scopes).toEqual(["source.python"]);
+      expect(tokens[36][1].value).toBe(".");
+      expect(tokens[36][1].scopes).toEqual(["source.python"]);
+      expect(tokens[36][2].value).toBe("__bytes__");
+      expect(tokens[36][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[37][0].value).toBe("some");
+      expect(tokens[37][0].scopes).toEqual(["source.python"]);
+      expect(tokens[37][1].value).toBe(".");
+      expect(tokens[37][1].scopes).toEqual(["source.python"]);
+      expect(tokens[37][2].value).toBe("__spec__");
+      expect(tokens[37][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[38][0].value).toBe("some");
+      expect(tokens[38][0].scopes).toEqual(["source.python"]);
+      expect(tokens[38][1].value).toBe(".");
+      expect(tokens[38][1].scopes).toEqual(["source.python"]);
+      expect(tokens[38][2].value).toBe("__path__");
+      expect(tokens[38][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[39][0].value).toBe("some");
+      expect(tokens[39][0].scopes).toEqual(["source.python"]);
+      expect(tokens[39][1].value).toBe(".");
+      expect(tokens[39][1].scopes).toEqual(["source.python"]);
+      expect(tokens[39][2].value).toBe("__prepare__");
+      expect(tokens[39][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[40][0].value).toBe("some");
+      expect(tokens[40][0].scopes).toEqual(["source.python"]);
+      expect(tokens[40][1].value).toBe(".");
+      expect(tokens[40][1].scopes).toEqual(["source.python"]);
+      expect(tokens[40][2].value).toBe("__package__");
+      expect(tokens[40][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[41][0].value).toBe("some");
+      expect(tokens[41][0].scopes).toEqual(["source.python"]);
+      expect(tokens[41][1].value).toBe(".");
+      expect(tokens[41][1].scopes).toEqual(["source.python"]);
+      expect(tokens[41][2].value).toBe("__notspecial__");
+      expect(tokens[41][2].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/builtins/builtins4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("some.int\nsome.sum\nsome.super\nsome.unicode\nsome.foo\nsome.Exception")
+      expect(tokens[0][0].value).toBe("some");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("int");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("some");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(".");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("sum");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("some");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(".");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("super");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("some");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(".");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("unicode");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("some");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe(".");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("foo");
+      expect(tokens[4][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("some");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe(".");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("Exception");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/builtins/builtins5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("some. True\nsome. \\\n    True\nTrue\nsome.\n    True")
+      expect(tokens[0][0].value).toBe("some");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(". ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("True");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[1][0].value).toBe("some");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(". ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("\\");
+      expect(tokens[1][2].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][3].value).toBe("");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("True");
+      expect(tokens[2][1].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[3][0].value).toBe("True");
+      expect(tokens[3][0].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[4][0].value).toBe("some");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe(".");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("True");
+      expect(tokens[5][1].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+    });
+
+  it("test/calls/call1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("some_call(A, b, c[1], *args, FOO=lambda:{'q': 42}, **kwargs)")
+      expect(tokens[0][0].value).toBe("some_call");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][2].value).toBe("A");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][3].value).toBe(",");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][5].value).toBe("b");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][6].value).toBe(",");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][8].value).toBe("c");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.item-access.python"]);
+      expect(tokens[0][9].value).toBe("[");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][10].value).toBe("1");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][11].value).toBe("]");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][12].value).toBe(",");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[0][13].value).toBe(" ");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][14].value).toBe("*");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[0][15].value).toBe("args");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][16].value).toBe(",");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[0][17].value).toBe(" ");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][18].value).toBe("FOO");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][19].value).toBe("=");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][20].value).toBe("lambda");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][21].value).toBe(":");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[0][22].value).toBe("{");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[0][23].value).toBe("'");
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][24].value).toBe("q");
+      expect(tokens[0][24].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[0][25].value).toBe("'");
+      expect(tokens[0][25].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][26].value).toBe(":");
+      expect(tokens[0][26].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.dict.python"]);
+      expect(tokens[0][27].value).toBe(" ");
+      expect(tokens[0][27].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][28].value).toBe("42");
+      expect(tokens[0][28].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][29].value).toBe("}");
+      expect(tokens[0][29].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[0][30].value).toBe(",");
+      expect(tokens[0][30].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[0][31].value).toBe(" ");
+      expect(tokens[0][31].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][32].value).toBe("**");
+      expect(tokens[0][32].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[0][33].value).toBe("kwargs");
+      expect(tokens[0][33].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][34].value).toBe(")");
+      expect(tokens[0][34].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/calls/call2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("foo(from=1)")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][2].value).toBe("from");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.control.flow.python"]);
+      expect(tokens[0][3].value).toBe("=");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][4].value).toBe("1");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][5].value).toBe(")");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/calls/call3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("foo.class(a)\nfoo.and()\nfoo.if")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("class");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","keyword.control.flow.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][4].value).toBe("a");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][5].value).toBe(")");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][0].value).toBe("foo");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(".");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("and");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","keyword.control.flow.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][0].value).toBe("foo");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(".");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("if");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/calls/call4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("foo.1\nfoo(bar=baz)(ham=sam)\nfoo.None and foo.None.baz")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("1");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("foo");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][1].value).toBe("(");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][2].value).toBe("bar");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[1][3].value).toBe("=");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][4].value).toBe("baz");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][5].value).toBe(")");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][6].value).toBe("(");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][7].value).toBe("ham");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[1][8].value).toBe("=");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][9].value).toBe("sam");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][10].value).toBe(")");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][0].value).toBe("foo");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(".");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("None");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("and");
+      expect(tokens[2][4].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("foo");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][7].value).toBe(".");
+      expect(tokens[2][7].scopes).toEqual(["source.python"]);
+      expect(tokens[2][8].value).toBe("None");
+      expect(tokens[2][8].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[2][9].value).toBe(".");
+      expect(tokens[2][9].scopes).toEqual(["source.python"]);
+      expect(tokens[2][10].value).toBe("baz");
+      expect(tokens[2][10].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/calls/call5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f(*a)\nf(**a)")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][2].value).toBe("*");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[0][3].value).toBe("a");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][0].value).toBe("f");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][1].value).toBe("(");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][2].value).toBe("**");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[1][3].value).toBe("a");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/calls/call6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f(  *a ,  *())\nf(  **a ,  **{})")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][2].value).toBe("  ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[0][3].value).toBe("*");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[0][4].value).toBe("a");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][6].value).toBe(",");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[0][7].value).toBe("  ");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][8].value).toBe("*");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[0][9].value).toBe("(");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[0][10].value).toBe(")");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[0][11].value).toBe(")");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][0].value).toBe("f");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][1].value).toBe("(");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][2].value).toBe("  ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[1][3].value).toBe("**");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[1][4].value).toBe("a");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][6].value).toBe(",");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[1][7].value).toBe("  ");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][8].value).toBe("**");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[1][9].value).toBe("{");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[1][10].value).toBe("}");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[1][11].value).toBe(")");
+      expect(tokens[1][11].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/calls/call7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("foo.__class__ (foo=bar)\nfoo.__class__(foo=bar)\nfoo.__add__ (foo=bar)\nfoo.__add__(foo=bar)\n\nfoo.__class__ 1")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("__class__");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[0][4].value).toBe("(");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][5].value).toBe("foo");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][6].value).toBe("=");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][7].value).toBe("bar");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][8].value).toBe(")");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][0].value).toBe("foo");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(".");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("__class__");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][4].value).toBe("foo");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[1][5].value).toBe("=");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][6].value).toBe("bar");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][7].value).toBe(")");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][0].value).toBe("foo");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(".");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("__add__");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[2][4].value).toBe("(");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][5].value).toBe("foo");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[2][6].value).toBe("=");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][7].value).toBe("bar");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[2][8].value).toBe(")");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][0].value).toBe("foo");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(".");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("__add__");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[3][3].value).toBe("(");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][4].value).toBe("foo");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][5].value).toBe("=");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][6].value).toBe("bar");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][7].value).toBe(")");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("foo");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe(".");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("__class__");
+      expect(tokens[5][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[5][3].value).toBe(" ");
+      expect(tokens[5][3].scopes).toEqual(["source.python"]);
+      expect(tokens[5][4].value).toBe("1");
+      expect(tokens[5][4].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/calls/call8.py", 
+    function() {
+      tokens = grammar.tokenizeLines("foo. __class__(foo=bar)\nfoo. __class__ (foo=bar)\nfoo. __add__ (foo=bar)\nfoo. __add__(foo=bar)")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(". ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("__class__");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][4].value).toBe("foo");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][5].value).toBe("=");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][6].value).toBe("bar");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][7].value).toBe(")");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][0].value).toBe("foo");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(". ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("__class__");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[1][4].value).toBe("(");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][5].value).toBe("foo");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[1][6].value).toBe("=");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][7].value).toBe("bar");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][8].value).toBe(")");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][0].value).toBe("foo");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(". ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("__add__");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[2][4].value).toBe("(");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][5].value).toBe("foo");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[2][6].value).toBe("=");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][7].value).toBe("bar");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[2][8].value).toBe(")");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][0].value).toBe("foo");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(". ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("__add__");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[3][3].value).toBe("(");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][4].value).toBe("foo");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][5].value).toBe("=");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][6].value).toBe("bar");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][7].value).toBe(")");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/calls/call9.py", 
+    function() {
+      tokens = grammar.tokenizeLines("foo(type=1)")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][2].value).toBe("type");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][3].value).toBe("=");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][4].value).toBe("1");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][5].value).toBe(")");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/calls/print1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("print \"is\", 2*2\nprint(\"is\", 2*2)\nprint x,\nprint(x, end=\" \")\nprint\nprint()\nprint >>sys.stderr, \"er\"\nprint(\"er\", file=sys.stderr)\nprint (x, y)\nprint((x, y))")
+      expect(tokens[0][0].value).toBe("print");
+      expect(tokens[0][0].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("\"");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][3].value).toBe("is");
+      expect(tokens[0][3].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][4].value).toBe("\"");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][5].value).toBe(",");
+      expect(tokens[0][5].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe("2");
+      expect(tokens[0][7].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][8].value).toBe("*");
+      expect(tokens[0][8].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][9].value).toBe("2");
+      expect(tokens[0][9].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][0].value).toBe("print");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[1][1].value).toBe("(");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][2].value).toBe("\"");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][3].value).toBe("is");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[1][4].value).toBe("\"");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][5].value).toBe(",");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][7].value).toBe("2");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[1][8].value).toBe("*");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[1][9].value).toBe("2");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[1][10].value).toBe(")");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][0].value).toBe("print");
+      expect(tokens[2][0].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("x");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe(",");
+      expect(tokens[2][3].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[3][0].value).toBe("print");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[3][1].value).toBe("(");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][2].value).toBe("x");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][3].value).toBe(",");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[3][4].value).toBe(" ");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][5].value).toBe("end");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][6].value).toBe("=");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][7].value).toBe("\"");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][8].value).toBe(" ");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[3][9].value).toBe("\"");
+      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][10].value).toBe(")");
+      expect(tokens[3][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[4][0].value).toBe("print");
+      expect(tokens[4][0].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[5][0].value).toBe("print");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[5][1].value).toBe("(");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[5][2].value).toBe(")");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[6][0].value).toBe("print");
+      expect(tokens[6][0].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].value).toBe(">>");
+      expect(tokens[6][2].scopes).toEqual(["source.python","keyword.operator.bitwise.python"]);
+      expect(tokens[6][3].value).toBe("sys");
+      expect(tokens[6][3].scopes).toEqual(["source.python"]);
+      expect(tokens[6][4].value).toBe(".");
+      expect(tokens[6][4].scopes).toEqual(["source.python"]);
+      expect(tokens[6][5].value).toBe("stderr");
+      expect(tokens[6][5].scopes).toEqual(["source.python"]);
+      expect(tokens[6][6].value).toBe(",");
+      expect(tokens[6][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[6][7].value).toBe(" ");
+      expect(tokens[6][7].scopes).toEqual(["source.python"]);
+      expect(tokens[6][8].value).toBe("\"");
+      expect(tokens[6][8].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][9].value).toBe("er");
+      expect(tokens[6][9].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[6][10].value).toBe("\"");
+      expect(tokens[6][10].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[7][0].value).toBe("print");
+      expect(tokens[7][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[7][1].value).toBe("(");
+      expect(tokens[7][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[7][2].value).toBe("\"");
+      expect(tokens[7][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][3].value).toBe("er");
+      expect(tokens[7][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[7][4].value).toBe("\"");
+      expect(tokens[7][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[7][5].value).toBe(",");
+      expect(tokens[7][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[7][6].value).toBe(" ");
+      expect(tokens[7][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[7][7].value).toBe("file");
+      expect(tokens[7][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[7][8].value).toBe("=");
+      expect(tokens[7][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[7][9].value).toBe("sys");
+      expect(tokens[7][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[7][10].value).toBe(".");
+      expect(tokens[7][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[7][11].value).toBe("stderr");
+      expect(tokens[7][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[7][12].value).toBe(")");
+      expect(tokens[7][12].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[8][0].value).toBe("print");
+      expect(tokens[8][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[8][1].value).toBe(" ");
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[8][2].value).toBe("(");
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[8][3].value).toBe("x");
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[8][4].value).toBe(",");
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[8][5].value).toBe(" ");
+      expect(tokens[8][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[8][6].value).toBe("y");
+      expect(tokens[8][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[8][7].value).toBe(")");
+      expect(tokens[8][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[9][0].value).toBe("print");
+      expect(tokens[9][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[9][1].value).toBe("(");
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[9][2].value).toBe("(");
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[9][3].value).toBe("x");
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[9][4].value).toBe(",");
+      expect(tokens[9][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.element.python"]);
+      expect(tokens[9][5].value).toBe(" ");
+      expect(tokens[9][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[9][6].value).toBe("y");
+      expect(tokens[9][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[9][7].value).toBe(")");
+      expect(tokens[9][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[9][8].value).toBe(")");
+      expect(tokens[9][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/classes/class1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Foo -> None: pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("Foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("->");
+      expect(tokens[0][4].scopes).toEqual(["source.python","invalid.illegal.annotation.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("None");
+      expect(tokens[0][6].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[0][7].value).toBe(":");
+      expect(tokens[0][7].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe("pass");
+      expect(tokens[0][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class10.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Foo(Bar(q=1) (w=2) (e=3)): pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[0][4].value).toBe("Bar");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][5].value).toBe("(");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][6].value).toBe("q");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][7].value).toBe("=");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][8].value).toBe("1");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][9].value).toBe(")");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][11].value).toBe("(");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][12].value).toBe("w");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][13].value).toBe("=");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][14].value).toBe("2");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][15].value).toBe(")");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][16].value).toBe(" ");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][17].value).toBe("(");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][18].value).toBe("e");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][19].value).toBe("=");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][20].value).toBe("3");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][21].value).toBe(")");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][22].value).toBe(")");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[0][23].value).toBe(":");
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[0][24].value).toBe(" ");
+      expect(tokens[0][24].scopes).toEqual(["source.python"]);
+      expect(tokens[0][25].value).toBe("pass");
+      expect(tokens[0][25].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class11.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class F:\n    def __init__(self, a, b=1):\n        self.a = a\n        self.b = b\n        print(self)\n        self()\n        a.self = 1\n        a.self.bar = 2\n        self[123]")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("F");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][1].value).toBe("def");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][3].value).toBe("__init__");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","support.function.magic.python"]);
+      expect(tokens[1][4].value).toBe("(");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][5].value).toBe("self");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python","variable.parameter.function.language.special.self.python"]);
+      expect(tokens[1][6].value).toBe(",");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[1][7].value).toBe(" ");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][8].value).toBe("a");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[1][9].value).toBe(",");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[1][10].value).toBe(" ");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][11].value).toBe("b");
+      expect(tokens[1][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[1][12].value).toBe("=");
+      expect(tokens[1][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[1][13].value).toBe("1");
+      expect(tokens[1][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[1][14].value).toBe(")");
+      expect(tokens[1][14].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][15].value).toBe(":");
+      expect(tokens[1][15].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[2][0].value).toBe("        ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("self");
+      expect(tokens[2][1].scopes).toEqual(["source.python","variable.language.special.self.python"]);
+      expect(tokens[2][2].value).toBe(".");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe("a");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe(" ");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][5].value).toBe("=");
+      expect(tokens[2][5].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][6].value).toBe(" ");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][7].value).toBe("a");
+      expect(tokens[2][7].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("        ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("self");
+      expect(tokens[3][1].scopes).toEqual(["source.python","variable.language.special.self.python"]);
+      expect(tokens[3][2].value).toBe(".");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("b");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe(" ");
+      expect(tokens[3][4].scopes).toEqual(["source.python"]);
+      expect(tokens[3][5].value).toBe("=");
+      expect(tokens[3][5].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][6].value).toBe(" ");
+      expect(tokens[3][6].scopes).toEqual(["source.python"]);
+      expect(tokens[3][7].value).toBe("b");
+      expect(tokens[3][7].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("        ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("print");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[4][2].value).toBe("(");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[4][3].value).toBe("self");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.language.special.self.python"]);
+      expect(tokens[4][4].value).toBe(")");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[5][0].value).toBe("        ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("self");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function-call.python","variable.language.special.self.python"]);
+      expect(tokens[5][2].value).toBe("(");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[5][3].value).toBe(")");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[6][0].value).toBe("        ");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe("a");
+      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].value).toBe(".");
+      expect(tokens[6][2].scopes).toEqual(["source.python"]);
+      expect(tokens[6][3].value).toBe("self");
+      expect(tokens[6][3].scopes).toEqual(["source.python"]);
+      expect(tokens[6][4].value).toBe(" ");
+      expect(tokens[6][4].scopes).toEqual(["source.python"]);
+      expect(tokens[6][5].value).toBe("=");
+      expect(tokens[6][5].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[6][6].value).toBe(" ");
+      expect(tokens[6][6].scopes).toEqual(["source.python"]);
+      expect(tokens[6][7].value).toBe("1");
+      expect(tokens[6][7].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[7][0].value).toBe("        ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("a");
+      expect(tokens[7][1].scopes).toEqual(["source.python"]);
+      expect(tokens[7][2].value).toBe(".");
+      expect(tokens[7][2].scopes).toEqual(["source.python"]);
+      expect(tokens[7][3].value).toBe("self");
+      expect(tokens[7][3].scopes).toEqual(["source.python"]);
+      expect(tokens[7][4].value).toBe(".");
+      expect(tokens[7][4].scopes).toEqual(["source.python"]);
+      expect(tokens[7][5].value).toBe("bar");
+      expect(tokens[7][5].scopes).toEqual(["source.python"]);
+      expect(tokens[7][6].value).toBe(" ");
+      expect(tokens[7][6].scopes).toEqual(["source.python"]);
+      expect(tokens[7][7].value).toBe("=");
+      expect(tokens[7][7].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[7][8].value).toBe(" ");
+      expect(tokens[7][8].scopes).toEqual(["source.python"]);
+      expect(tokens[7][9].value).toBe("2");
+      expect(tokens[7][9].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[8][0].value).toBe("        ");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe("self");
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.item-access.python","variable.language.special.self.python"]);
+      expect(tokens[8][2].value).toBe("[");
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[8][3].value).toBe("123");
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[8][4].value).toBe("]");
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/classes/class12.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class F:\n    @classmethod\n    def meth(cls, a, b=1):\n        cls.a = a\n        cls.b = b\n        print(cls)\n        cls()\n        cls + 1\n        a.cls = 1\n        a.cls.__name__\n        cls[123]")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("F");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[1][1].value).toBe("@");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][2].value).toBe("classmethod");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python","support.type.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][1].value).toBe("def");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][3].value).toBe("meth");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[2][4].value).toBe("(");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[2][5].value).toBe("cls");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python","variable.parameter.function.language.special.cls.python"]);
+      expect(tokens[2][6].value).toBe(",");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[2][7].value).toBe(" ");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[2][8].value).toBe("a");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[2][9].value).toBe(",");
+      expect(tokens[2][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[2][10].value).toBe(" ");
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[2][11].value).toBe("b");
+      expect(tokens[2][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[2][12].value).toBe("=");
+      expect(tokens[2][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[2][13].value).toBe("1");
+      expect(tokens[2][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[2][14].value).toBe(")");
+      expect(tokens[2][14].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[2][15].value).toBe(":");
+      expect(tokens[2][15].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[3][0].value).toBe("        ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("cls");
+      expect(tokens[3][1].scopes).toEqual(["source.python","variable.language.special.cls.python"]);
+      expect(tokens[3][2].value).toBe(".");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("a");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe(" ");
+      expect(tokens[3][4].scopes).toEqual(["source.python"]);
+      expect(tokens[3][5].value).toBe("=");
+      expect(tokens[3][5].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][6].value).toBe(" ");
+      expect(tokens[3][6].scopes).toEqual(["source.python"]);
+      expect(tokens[3][7].value).toBe("a");
+      expect(tokens[3][7].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("        ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("cls");
+      expect(tokens[4][1].scopes).toEqual(["source.python","variable.language.special.cls.python"]);
+      expect(tokens[4][2].value).toBe(".");
+      expect(tokens[4][2].scopes).toEqual(["source.python"]);
+      expect(tokens[4][3].value).toBe("b");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe(" ");
+      expect(tokens[4][4].scopes).toEqual(["source.python"]);
+      expect(tokens[4][5].value).toBe("=");
+      expect(tokens[4][5].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][6].value).toBe(" ");
+      expect(tokens[4][6].scopes).toEqual(["source.python"]);
+      expect(tokens[4][7].value).toBe("b");
+      expect(tokens[4][7].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("        ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("print");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[5][2].value).toBe("(");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[5][3].value).toBe("cls");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.language.special.cls.python"]);
+      expect(tokens[5][4].value).toBe(")");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[6][0].value).toBe("        ");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe("cls");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function-call.python","variable.language.special.cls.python"]);
+      expect(tokens[6][2].value).toBe("(");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[6][3].value).toBe(")");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[7][0].value).toBe("        ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("cls");
+      expect(tokens[7][1].scopes).toEqual(["source.python","variable.language.special.cls.python"]);
+      expect(tokens[7][2].value).toBe(" ");
+      expect(tokens[7][2].scopes).toEqual(["source.python"]);
+      expect(tokens[7][3].value).toBe("+");
+      expect(tokens[7][3].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[7][4].value).toBe(" ");
+      expect(tokens[7][4].scopes).toEqual(["source.python"]);
+      expect(tokens[7][5].value).toBe("1");
+      expect(tokens[7][5].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[8][0].value).toBe("        ");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe("a");
+      expect(tokens[8][1].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].value).toBe(".");
+      expect(tokens[8][2].scopes).toEqual(["source.python"]);
+      expect(tokens[8][3].value).toBe("cls");
+      expect(tokens[8][3].scopes).toEqual(["source.python"]);
+      expect(tokens[8][4].value).toBe(" ");
+      expect(tokens[8][4].scopes).toEqual(["source.python"]);
+      expect(tokens[8][5].value).toBe("=");
+      expect(tokens[8][5].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[8][6].value).toBe(" ");
+      expect(tokens[8][6].scopes).toEqual(["source.python"]);
+      expect(tokens[8][7].value).toBe("1");
+      expect(tokens[8][7].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[9][0].value).toBe("        ");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].value).toBe("a");
+      expect(tokens[9][1].scopes).toEqual(["source.python"]);
+      expect(tokens[9][2].value).toBe(".");
+      expect(tokens[9][2].scopes).toEqual(["source.python"]);
+      expect(tokens[9][3].value).toBe("cls");
+      expect(tokens[9][3].scopes).toEqual(["source.python"]);
+      expect(tokens[9][4].value).toBe(".");
+      expect(tokens[9][4].scopes).toEqual(["source.python"]);
+      expect(tokens[9][5].value).toBe("__name__");
+      expect(tokens[9][5].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[10][0].value).toBe("        ");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe("cls");
+      expect(tokens[10][1].scopes).toEqual(["source.python","meta.item-access.python","variable.language.special.cls.python"]);
+      expect(tokens[10][2].value).toBe("[");
+      expect(tokens[10][2].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[10][3].value).toBe("123");
+      expect(tokens[10][3].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[10][4].value).toBe("]");
+      expect(tokens[10][4].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/classes/class13.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class A(*a, **b): pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("A");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[0][4].value).toBe("*");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[0][5].value).toBe("a");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][6].value).toBe(",");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][8].value).toBe("**");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[0][9].value).toBe("b");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][10].value).toBe(")");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[0][11].value).toBe(":");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[0][12].value).toBe(" ");
+      expect(tokens[0][12].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].value).toBe("pass");
+      expect(tokens[0][13].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class14.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class F(f.Exception, f.type, Exception, Exception.a, b=Exception):\n    pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("F");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[0][4].value).toBe("f");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][5].value).toBe(".");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][6].value).toBe("Exception");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][7].value).toBe(",");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][9].value).toBe("f");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][10].value).toBe(".");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][11].value).toBe("type");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][12].value).toBe(",");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[0][13].value).toBe(" ");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][14].value).toBe("Exception");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","support.type.exception.python"]);
+      expect(tokens[0][15].value).toBe(",");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[0][16].value).toBe(" ");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][17].value).toBe("Exception");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","support.type.exception.python"]);
+      expect(tokens[0][18].value).toBe(".");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][19].value).toBe("a");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][20].value).toBe(",");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[0][21].value).toBe(" ");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][22].value).toBe("b");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","variable.parameter.class.python entity.other.inherited-class.python"]);
+      expect(tokens[0][23].value).toBe("=");
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][24].value).toBe("Exception");
+      expect(tokens[0][24].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","support.type.exception.python"]);
+      expect(tokens[0][25].value).toBe(")");
+      expect(tokens[0][25].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[0][26].value).toBe(":");
+      expect(tokens[0][26].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("pass");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class15.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Spam(Foo, from==12):\n    pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Spam");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[0][4].value).toBe("Foo");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][5].value).toBe(",");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][7].value).toBe("from");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.control.flow.python"]);
+      expect(tokens[0][8].value).toBe("==");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.operator.comparison.python"]);
+      expect(tokens[0][9].value).toBe("12");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","constant.numeric.dec.python"]);
+      expect(tokens[0][10].value).toBe(")");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[0][11].value).toBe(":");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("pass");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class16.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Foo(Bar, str, type=12, metaclass=FooMeta): pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[0][4].value).toBe("Bar");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][5].value).toBe(",");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][7].value).toBe("str");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","support.type.python"]);
+      expect(tokens[0][8].value).toBe(",");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][10].value).toBe("type");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","variable.parameter.class.python entity.other.inherited-class.python"]);
+      expect(tokens[0][11].value).toBe("=");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][12].value).toBe("12");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","constant.numeric.dec.python"]);
+      expect(tokens[0][13].value).toBe(",");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[0][14].value).toBe(" ");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][15].value).toBe("metaclass");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","support.type.metaclass.python"]);
+      expect(tokens[0][16].value).toBe("=");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][17].value).toBe("FooMeta");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][18].value).toBe(")");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[0][19].value).toBe(":");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[0][20].value).toBe(" ");
+      expect(tokens[0][20].scopes).toEqual(["source.python"]);
+      expect(tokens[0][21].value).toBe("pass");
+      expect(tokens[0][21].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("@dec\n# Bar.name=... is not legal, but the test is for highlighter not breaking badly\nclass Spam(Foo.Bar, Bar.name={'very': 'odd'}):\n    pass")
+      expect(tokens[0][0].value).toBe("@");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][1].value).toBe("dec");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][0].value).toBe("#");
+      expect(tokens[1][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][1].value).toBe(" Bar.name=... is not legal, but the test is for highlighter not breaking badly");
+      expect(tokens[1][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[2][0].value).toBe("class");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[2][2].value).toBe("Spam");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[2][4].value).toBe("Foo");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[2][5].value).toBe(".");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[2][6].value).toBe("Bar");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[2][7].value).toBe(",");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[2][8].value).toBe(" ");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[2][9].value).toBe("Bar");
+      expect(tokens[2][9].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[2][10].value).toBe(".");
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[2][11].value).toBe("name");
+      expect(tokens[2][11].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[2][12].value).toBe("=");
+      expect(tokens[2][12].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][13].value).toBe("{");
+      expect(tokens[2][13].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[2][14].value).toBe("'");
+      expect(tokens[2][14].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][15].value).toBe("very");
+      expect(tokens[2][15].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","string.quoted.single.python"]);
+      expect(tokens[2][16].value).toBe("'");
+      expect(tokens[2][16].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][17].value).toBe(":");
+      expect(tokens[2][17].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.dict.python"]);
+      expect(tokens[2][18].value).toBe(" ");
+      expect(tokens[2][18].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[2][19].value).toBe("'");
+      expect(tokens[2][19].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][20].value).toBe("odd");
+      expect(tokens[2][20].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","string.quoted.single.python"]);
+      expect(tokens[2][21].value).toBe("'");
+      expect(tokens[2][21].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][22].value).toBe("}");
+      expect(tokens[2][22].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[2][23].value).toBe(")");
+      expect(tokens[2][23].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[2][24].value).toBe(":");
+      expect(tokens[2][24].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("pass");
+      expect(tokens[3][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Spam(Foo, from=12):\n    pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Spam");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[0][4].value).toBe("Foo");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][5].value).toBe(",");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][7].value).toBe("from");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.control.flow.python"]);
+      expect(tokens[0][8].value).toBe("=");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][9].value).toBe("12");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","constant.numeric.dec.python"]);
+      expect(tokens[0][10].value).toBe(")");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[0][11].value).toBe(":");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("pass");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Exception: pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Exception");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","support.type.exception.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("pass");
+      expect(tokens[0][5].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Foo(Exception, MyObj): pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[0][4].value).toBe("Exception");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","support.type.exception.python"]);
+      expect(tokens[0][5].value).toBe(",");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][7].value).toBe("MyObj");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][8].value).toBe(")");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[0][9].value).toBe(":");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe("pass");
+      expect(tokens[0][11].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Foo(metaclass=FooMeta): pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[0][4].value).toBe("metaclass");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","support.type.metaclass.python"]);
+      expect(tokens[0][5].value).toBe("=");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][6].value).toBe("FooMeta");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][7].value).toBe(")");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[0][8].value).toBe(":");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("pass");
+      expect(tokens[0][10].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class class:\n    pass\n# doesn't break")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("class");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","keyword.control.flow.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("pass");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][0].value).toBe("#");
+      expect(tokens[2][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][1].value).toBe(" doesn't break");
+      expect(tokens[2][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/classes/class8.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class None: pass\nclass True(False): pass\nclass False(object): pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("None");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","keyword.illegal.name.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("pass");
+      expect(tokens[0][5].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][0].value).toBe("class");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[1][2].value).toBe("True");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.class.python","keyword.illegal.name.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[1][4].value).toBe("False");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","constant.language.python"]);
+      expect(tokens[1][5].value).toBe(")");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[1][6].value).toBe(":");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][7].value).toBe(" ");
+      expect(tokens[1][7].scopes).toEqual(["source.python"]);
+      expect(tokens[1][8].value).toBe("pass");
+      expect(tokens[1][8].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][0].value).toBe("class");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[2][2].value).toBe("False");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.class.python","keyword.illegal.name.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[2][4].value).toBe("object");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","support.type.python"]);
+      expect(tokens[2][5].value).toBe(")");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[2][6].value).toBe(":");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[2][7].value).toBe(" ");
+      expect(tokens[2][7].scopes).toEqual(["source.python"]);
+      expect(tokens[2][8].value).toBe("pass");
+      expect(tokens[2][8].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/classes/class9.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Foo:\n    __slots__ = ()")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("__slots__");
+      expect(tokens[1][1].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("=");
+      expect(tokens[1][3].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][4].value).toBe(" ");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][5].value).toBe("(");
+      expect(tokens[1][5].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[1][6].value).toBe(")");
+      expect(tokens[1][6].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+    });
+
+  it("test/classes/super1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Foo:\n    def __init__(self):\n        super().__init__(foo=1)\n        super(). __init__(foo=1)\n        super(). \\\n__init__(foo=1)\n        __init__(foo=1)\n\n        foo.__init__(bar=1)\n        __init__(bar=1)\n        if:\n            __init__(bar=1)")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][1].value).toBe("def");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][3].value).toBe("__init__");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","support.function.magic.python"]);
+      expect(tokens[1][4].value).toBe("(");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][5].value).toBe("self");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python","variable.parameter.function.language.special.self.python"]);
+      expect(tokens[1][6].value).toBe(")");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][7].value).toBe(":");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[2][0].value).toBe("        ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("super");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function-call.python","support.type.python"]);
+      expect(tokens[2][2].value).toBe("(");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][3].value).toBe(")");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][4].value).toBe(".");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][5].value).toBe("__init__");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[2][6].value).toBe("(");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][7].value).toBe("foo");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[2][8].value).toBe("=");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][9].value).toBe("1");
+      expect(tokens[2][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[2][10].value).toBe(")");
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][0].value).toBe("        ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("super");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function-call.python","support.type.python"]);
+      expect(tokens[3][2].value).toBe("(");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][3].value).toBe(")");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][4].value).toBe(". ");
+      expect(tokens[3][4].scopes).toEqual(["source.python"]);
+      expect(tokens[3][5].value).toBe("__init__");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[3][6].value).toBe("(");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][7].value).toBe("foo");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][8].value).toBe("=");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][9].value).toBe("1");
+      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[3][10].value).toBe(")");
+      expect(tokens[3][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[4][0].value).toBe("        ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("super");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function-call.python","support.type.python"]);
+      expect(tokens[4][2].value).toBe("(");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[4][3].value).toBe(")");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[4][4].value).toBe(". ");
+      expect(tokens[4][4].scopes).toEqual(["source.python"]);
+      expect(tokens[4][5].value).toBe("\\");
+      expect(tokens[4][5].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[4][6].value).toBe("");
+      expect(tokens[4][6].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("__init__");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[5][1].value).toBe("(");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[5][2].value).toBe("foo");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[5][3].value).toBe("=");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[5][4].value).toBe("1");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[5][5].value).toBe(")");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[6][0].value).toBe("        ");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe("__init__");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[6][2].value).toBe("(");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[6][3].value).toBe("foo");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[6][4].value).toBe("=");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[6][5].value).toBe("1");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[6][6].value).toBe(")");
+      expect(tokens[6][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[7][0].value).toBe("");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][0].value).toBe("        ");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe("foo");
+      expect(tokens[8][1].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].value).toBe(".");
+      expect(tokens[8][2].scopes).toEqual(["source.python"]);
+      expect(tokens[8][3].value).toBe("__init__");
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[8][4].value).toBe("(");
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[8][5].value).toBe("bar");
+      expect(tokens[8][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[8][6].value).toBe("=");
+      expect(tokens[8][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[8][7].value).toBe("1");
+      expect(tokens[8][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[8][8].value).toBe(")");
+      expect(tokens[8][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[9][0].value).toBe("        ");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].value).toBe("__init__");
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[9][2].value).toBe("(");
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[9][3].value).toBe("bar");
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[9][4].value).toBe("=");
+      expect(tokens[9][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[9][5].value).toBe("1");
+      expect(tokens[9][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[9][6].value).toBe(")");
+      expect(tokens[9][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[10][0].value).toBe("        ");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe("if");
+      expect(tokens[10][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[10][2].value).toBe(":");
+      expect(tokens[10][2].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[11][0].value).toBe("            ");
+      expect(tokens[11][0].scopes).toEqual(["source.python"]);
+      expect(tokens[11][1].value).toBe("__init__");
+      expect(tokens[11][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[11][2].value).toBe("(");
+      expect(tokens[11][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[11][3].value).toBe("bar");
+      expect(tokens[11][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[11][4].value).toBe("=");
+      expect(tokens[11][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[11][5].value).toBe("1");
+      expect(tokens[11][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[11][6].value).toBe(")");
+      expect(tokens[11][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/comments/comment1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# XXX foo\n# FIXME: bug\n# NB: XXXx xXXX but XXX!\n# ALSO HACK and NOTE and TODO highlight XXX and FIXME.")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[0][2].value).toBe("XXX");
+      expect(tokens[0][2].scopes).toEqual(["source.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[0][3].value).toBe(" foo");
+      expect(tokens[0][3].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("#");
+      expect(tokens[1][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][2].value).toBe("FIXME");
+      expect(tokens[1][2].scopes).toEqual(["source.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[1][3].value).toBe(": bug");
+      expect(tokens[1][3].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[2][0].value).toBe("#");
+      expect(tokens[2][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][1].value).toBe(" NB: XXXx xXXX but ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[2][2].value).toBe("XXX");
+      expect(tokens[2][2].scopes).toEqual(["source.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[2][3].value).toBe("!");
+      expect(tokens[2][3].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[3][0].value).toBe("#");
+      expect(tokens[3][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][1].value).toBe(" ALSO ");
+      expect(tokens[3][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[3][2].value).toBe("HACK");
+      expect(tokens[3][2].scopes).toEqual(["source.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[3][3].value).toBe(" and ");
+      expect(tokens[3][3].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[3][4].value).toBe("NOTE");
+      expect(tokens[3][4].scopes).toEqual(["source.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[3][5].value).toBe(" and ");
+      expect(tokens[3][5].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[3][6].value).toBe("TODO");
+      expect(tokens[3][6].scopes).toEqual(["source.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[3][7].value).toBe(" highlight ");
+      expect(tokens[3][7].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[3][8].value).toBe("XXX");
+      expect(tokens[3][8].scopes).toEqual(["source.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[3][9].value).toBe(" and ");
+      expect(tokens[3][9].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[3][10].value).toBe("FIXME");
+      expect(tokens[3][10].scopes).toEqual(["source.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[3][11].value).toBe(".");
+      expect(tokens[3][11].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/comments/typing1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# type: ignore  # test\n# type:  ignore\n# type:ignore\n#type:ignore\n# type: ignore 1\n# type: 1 ignore\n# type : ignore\n##type: ignore\n#.type: ignore")
+      expect(tokens[0][0].value).toBe("# ");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[0][1].value).toBe("type:");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.directive.notation.python"]);
+      expect(tokens[0][2].value).toBe(" ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[0][3].value).toBe("ignore");
+      expect(tokens[0][3].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.ignore.notation.python"]);
+      expect(tokens[0][4].value).toBe("  ");
+      expect(tokens[0][4].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[0][5].value).toBe("#");
+      expect(tokens[0][5].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][6].value).toBe(" test");
+      expect(tokens[0][6].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("# ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[1][1].value).toBe("type:");
+      expect(tokens[1][1].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.directive.notation.python"]);
+      expect(tokens[1][2].value).toBe("  ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[1][3].value).toBe("ignore");
+      expect(tokens[1][3].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.ignore.notation.python"]);
+      expect(tokens[2][0].value).toBe("# ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[2][1].value).toBe("type:");
+      expect(tokens[2][1].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.directive.notation.python"]);
+      expect(tokens[2][2].value).toBe("ignore");
+      expect(tokens[2][2].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.ignore.notation.python"]);
+      expect(tokens[3][0].value).toBe("#");
+      expect(tokens[3][0].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[3][1].value).toBe("type:");
+      expect(tokens[3][1].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.directive.notation.python"]);
+      expect(tokens[3][2].value).toBe("ignore");
+      expect(tokens[3][2].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.ignore.notation.python"]);
+      expect(tokens[4][0].value).toBe("# ");
+      expect(tokens[4][0].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[4][1].value).toBe("type:");
+      expect(tokens[4][1].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.directive.notation.python"]);
+      expect(tokens[4][2].value).toBe(" ");
+      expect(tokens[4][2].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[4][3].value).toBe("ignore");
+      expect(tokens[4][3].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.variable.notation.python"]);
+      expect(tokens[4][4].value).toBe(" 1");
+      expect(tokens[4][4].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[5][0].value).toBe("# ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[5][1].value).toBe("type:");
+      expect(tokens[5][1].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.directive.notation.python"]);
+      expect(tokens[5][2].value).toBe(" ");
+      expect(tokens[5][2].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[5][3].value).toBe("1 ");
+      expect(tokens[5][3].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[5][4].value).toBe("ignore");
+      expect(tokens[5][4].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.variable.notation.python"]);
+      expect(tokens[6][0].value).toBe("#");
+      expect(tokens[6][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[6][1].value).toBe(" type : ignore");
+      expect(tokens[6][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[7][0].value).toBe("#");
+      expect(tokens[7][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[7][1].value).toBe("#type: ignore");
+      expect(tokens[7][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[8][0].value).toBe("#");
+      expect(tokens[8][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[8][1].value).toBe(".type: ignore");
+      expect(tokens[8][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/comments/typing2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = 1 # type:\na = 1 # type: # 123")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("1");
+      expect(tokens[0][4].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("#");
+      expect(tokens[0][6].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][7].value).toBe(" type:");
+      expect(tokens[0][7].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("1");
+      expect(tokens[1][4].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("#");
+      expect(tokens[1][6].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][7].value).toBe(" type: # 123");
+      expect(tokens[1][7].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/comments/typing3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# abc type: def")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" abc type: def");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/comments/typing4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("x = None # type: List[str, a]\ny = None # type: Dict[int, Any] # int")
+      expect(tokens[0][0].value).toBe("x");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("None");
+      expect(tokens[0][4].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("# ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[0][7].value).toBe("type:");
+      expect(tokens[0][7].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.directive.notation.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[0][9].value).toBe("List");
+      expect(tokens[0][9].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.type.notation.python"]);
+      expect(tokens[0][10].value).toBe("[");
+      expect(tokens[0][10].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.punctuation.notation.python"]);
+      expect(tokens[0][11].value).toBe("str");
+      expect(tokens[0][11].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.type.notation.python"]);
+      expect(tokens[0][12].value).toBe(",");
+      expect(tokens[0][12].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.punctuation.notation.python"]);
+      expect(tokens[0][13].value).toBe(" ");
+      expect(tokens[0][13].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[0][14].value).toBe("a");
+      expect(tokens[0][14].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.variable.notation.python"]);
+      expect(tokens[0][15].value).toBe("]");
+      expect(tokens[0][15].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.punctuation.notation.python"]);
+      expect(tokens[1][0].value).toBe("y");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("None");
+      expect(tokens[1][4].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("# ");
+      expect(tokens[1][6].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[1][7].value).toBe("type:");
+      expect(tokens[1][7].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.directive.notation.python"]);
+      expect(tokens[1][8].value).toBe(" ");
+      expect(tokens[1][8].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[1][9].value).toBe("Dict");
+      expect(tokens[1][9].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.type.notation.python"]);
+      expect(tokens[1][10].value).toBe("[");
+      expect(tokens[1][10].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.punctuation.notation.python"]);
+      expect(tokens[1][11].value).toBe("int");
+      expect(tokens[1][11].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.type.notation.python"]);
+      expect(tokens[1][12].value).toBe(",");
+      expect(tokens[1][12].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.punctuation.notation.python"]);
+      expect(tokens[1][13].value).toBe(" ");
+      expect(tokens[1][13].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[1][14].value).toBe("Any");
+      expect(tokens[1][14].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.type.notation.python"]);
+      expect(tokens[1][15].value).toBe("]");
+      expect(tokens[1][15].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.punctuation.notation.python"]);
+      expect(tokens[1][16].value).toBe(" ");
+      expect(tokens[1][16].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[1][17].value).toBe("#");
+      expect(tokens[1][17].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][18].value).toBe(" int");
+      expect(tokens[1][18].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/comments/typing5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("if isinstance(t1, TypeVar): # type: ignore\n    continue")
+      expect(tokens[0][0].value).toBe("if");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("isinstance");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][4].value).toBe("t1");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][5].value).toBe(",");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][7].value).toBe("TypeVar");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][8].value).toBe(")");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][9].value).toBe(":");
+      expect(tokens[0][9].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe("# ");
+      expect(tokens[0][11].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[0][12].value).toBe("type:");
+      expect(tokens[0][12].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.directive.notation.python"]);
+      expect(tokens[0][13].value).toBe(" ");
+      expect(tokens[0][13].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[0][14].value).toBe("ignore");
+      expect(tokens[0][14].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.ignore.notation.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("continue");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/comments/typing6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a=1#type:int\na=1#type:int#int")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe("=");
+      expect(tokens[0][1].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][2].value).toBe("1");
+      expect(tokens[0][2].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][3].value).toBe("#");
+      expect(tokens[0][3].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[0][4].value).toBe("type:");
+      expect(tokens[0][4].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.directive.notation.python"]);
+      expect(tokens[0][5].value).toBe("int");
+      expect(tokens[0][5].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.type.notation.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("=");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][2].value).toBe("1");
+      expect(tokens[1][2].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][3].value).toBe("#");
+      expect(tokens[1][3].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python"]);
+      expect(tokens[1][4].value).toBe("type:");
+      expect(tokens[1][4].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.directive.notation.python"]);
+      expect(tokens[1][5].value).toBe("int");
+      expect(tokens[1][5].scopes).toEqual(["source.python","comment.line.number-sign.python","meta.typehint.comment.python","comment.typehint.type.notation.python"]);
+      expect(tokens[1][6].value).toBe("#");
+      expect(tokens[1][6].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][7].value).toBe("int");
+      expect(tokens[1][7].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/docstrings/class1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Foo:\n    '''TEST'''\n\nclass Foo:\n    r'''TEST'''\n\nclass Foo:\n    R'''TEST'''\n\nclass Foo:\n    u'''TEST'''\n\nclass Foo:\n    U'''TEST'''\n\nclass Foo:\n    b'''TEST'''\n\nclass Foo:\n    B'''TEST'''")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("'''");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("TEST");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[1][3].value).toBe("'''");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("class");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[3][2].value).toBe("Foo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[3][3].value).toBe(":");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("r");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[4][2].value).toBe("'''");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][3].value).toBe("TEST");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][4].value).toBe("'''");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("class");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[6][2].value).toBe("Foo");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[6][3].value).toBe(":");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("R");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[7][2].value).toBe("'''");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][3].value).toBe("TEST");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[7][4].value).toBe("'''");
+      expect(tokens[7][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][0].value).toBe("class");
+      expect(tokens[9][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[9][1].value).toBe(" ");
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[9][2].value).toBe("Foo");
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[9][3].value).toBe(":");
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[10][0].value).toBe("    ");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe("u");
+      expect(tokens[10][1].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[10][2].value).toBe("'''");
+      expect(tokens[10][2].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][3].value).toBe("TEST");
+      expect(tokens[10][3].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[10][4].value).toBe("'''");
+      expect(tokens[10][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[11][0].value).toBe("");
+      expect(tokens[11][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][0].value).toBe("class");
+      expect(tokens[12][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[12][1].value).toBe(" ");
+      expect(tokens[12][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[12][2].value).toBe("Foo");
+      expect(tokens[12][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[12][3].value).toBe(":");
+      expect(tokens[12][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[13][0].value).toBe("    ");
+      expect(tokens[13][0].scopes).toEqual(["source.python"]);
+      expect(tokens[13][1].value).toBe("U");
+      expect(tokens[13][1].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[13][2].value).toBe("'''");
+      expect(tokens[13][2].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[13][3].value).toBe("TEST");
+      expect(tokens[13][3].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[13][4].value).toBe("'''");
+      expect(tokens[13][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[14][0].value).toBe("");
+      expect(tokens[14][0].scopes).toEqual(["source.python"]);
+      expect(tokens[15][0].value).toBe("class");
+      expect(tokens[15][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[15][1].value).toBe(" ");
+      expect(tokens[15][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[15][2].value).toBe("Foo");
+      expect(tokens[15][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[15][3].value).toBe(":");
+      expect(tokens[15][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[16][0].value).toBe("    ");
+      expect(tokens[16][0].scopes).toEqual(["source.python"]);
+      expect(tokens[16][1].value).toBe("b");
+      expect(tokens[16][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[16][2].value).toBe("'''");
+      expect(tokens[16][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[16][3].value).toBe("TEST");
+      expect(tokens[16][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[16][4].value).toBe("'''");
+      expect(tokens[16][4].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[17][0].value).toBe("");
+      expect(tokens[17][0].scopes).toEqual(["source.python"]);
+      expect(tokens[18][0].value).toBe("class");
+      expect(tokens[18][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[18][1].value).toBe(" ");
+      expect(tokens[18][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[18][2].value).toBe("Foo");
+      expect(tokens[18][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[18][3].value).toBe(":");
+      expect(tokens[18][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[19][0].value).toBe("    ");
+      expect(tokens[19][0].scopes).toEqual(["source.python"]);
+      expect(tokens[19][1].value).toBe("B");
+      expect(tokens[19][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[19][2].value).toBe("'''");
+      expect(tokens[19][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[19][3].value).toBe("TEST");
+      expect(tokens[19][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[19][4].value).toBe("'''");
+      expect(tokens[19][4].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/class2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Foo:\n    \"\"\"TEST\"\"\"\n\nclass Foo:\n    r\"\"\"TEST\"\"\"\n\nclass Foo:\n    R\"\"\"TEST\"\"\"\n\nclass Foo:\n    u\"\"\"TEST\"\"\"\n\nclass Foo:\n    U\"\"\"TEST\"\"\"\n\nclass Foo:\n    b\"\"\"TEST\"\"\"\n\nclass Foo:\n    B\"\"\"TEST\"\"\"")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("\"\"\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("TEST");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[1][3].value).toBe("\"\"\"");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("class");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[3][2].value).toBe("Foo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[3][3].value).toBe(":");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("r");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[4][2].value).toBe("\"\"\"");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][3].value).toBe("TEST");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][4].value).toBe("\"\"\"");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("class");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[6][2].value).toBe("Foo");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[6][3].value).toBe(":");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("R");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[7][2].value).toBe("\"\"\"");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][3].value).toBe("TEST");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[7][4].value).toBe("\"\"\"");
+      expect(tokens[7][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][0].value).toBe("class");
+      expect(tokens[9][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[9][1].value).toBe(" ");
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[9][2].value).toBe("Foo");
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[9][3].value).toBe(":");
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[10][0].value).toBe("    ");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe("u");
+      expect(tokens[10][1].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[10][2].value).toBe("\"\"\"");
+      expect(tokens[10][2].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][3].value).toBe("TEST");
+      expect(tokens[10][3].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[10][4].value).toBe("\"\"\"");
+      expect(tokens[10][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[11][0].value).toBe("");
+      expect(tokens[11][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][0].value).toBe("class");
+      expect(tokens[12][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[12][1].value).toBe(" ");
+      expect(tokens[12][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[12][2].value).toBe("Foo");
+      expect(tokens[12][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[12][3].value).toBe(":");
+      expect(tokens[12][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[13][0].value).toBe("    ");
+      expect(tokens[13][0].scopes).toEqual(["source.python"]);
+      expect(tokens[13][1].value).toBe("U");
+      expect(tokens[13][1].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[13][2].value).toBe("\"\"\"");
+      expect(tokens[13][2].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[13][3].value).toBe("TEST");
+      expect(tokens[13][3].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[13][4].value).toBe("\"\"\"");
+      expect(tokens[13][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[14][0].value).toBe("");
+      expect(tokens[14][0].scopes).toEqual(["source.python"]);
+      expect(tokens[15][0].value).toBe("class");
+      expect(tokens[15][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[15][1].value).toBe(" ");
+      expect(tokens[15][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[15][2].value).toBe("Foo");
+      expect(tokens[15][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[15][3].value).toBe(":");
+      expect(tokens[15][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[16][0].value).toBe("    ");
+      expect(tokens[16][0].scopes).toEqual(["source.python"]);
+      expect(tokens[16][1].value).toBe("b");
+      expect(tokens[16][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[16][2].value).toBe("\"\"\"");
+      expect(tokens[16][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[16][3].value).toBe("TEST");
+      expect(tokens[16][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[16][4].value).toBe("\"\"\"");
+      expect(tokens[16][4].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[17][0].value).toBe("");
+      expect(tokens[17][0].scopes).toEqual(["source.python"]);
+      expect(tokens[18][0].value).toBe("class");
+      expect(tokens[18][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[18][1].value).toBe(" ");
+      expect(tokens[18][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[18][2].value).toBe("Foo");
+      expect(tokens[18][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[18][3].value).toBe(":");
+      expect(tokens[18][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[19][0].value).toBe("    ");
+      expect(tokens[19][0].scopes).toEqual(["source.python"]);
+      expect(tokens[19][1].value).toBe("B");
+      expect(tokens[19][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[19][2].value).toBe("\"\"\"");
+      expect(tokens[19][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[19][3].value).toBe("TEST");
+      expect(tokens[19][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[19][4].value).toBe("\"\"\"");
+      expect(tokens[19][4].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/codetag1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("''' foo bar XXX baz '''\n\ndef foo():\n    ''' foo FIXME baz '''")
+      expect(tokens[0][0].value).toBe("'''");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe(" foo bar ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[0][2].value).toBe("XXX");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","keyword.codetag.notation.python"]);
+      expect(tokens[0][3].value).toBe(" baz ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[0][4].value).toBe("'''");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("def");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][2].value).toBe("foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[2][4].value).toBe(")");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[2][5].value).toBe(":");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("'''");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe(" foo ");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][3].value).toBe("FIXME");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","keyword.codetag.notation.python"]);
+      expect(tokens[3][4].value).toBe(" baz ");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][5].value).toBe("'''");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/codetag2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("' foo bar XXX baz '\n\ndef foo():\n    ' foo FIXME baz '")
+      expect(tokens[0][0].value).toBe("'");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe(" foo bar ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[0][2].value).toBe("XXX");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python","keyword.codetag.notation.python"]);
+      expect(tokens[0][3].value).toBe(" baz ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("def");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][2].value).toBe("foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[2][4].value).toBe(")");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[2][5].value).toBe(":");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("'");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe(" foo ");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[3][3].value).toBe("FIXME");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.quoted.docstring.single.python","keyword.codetag.notation.python"]);
+      expect(tokens[3][4].value).toBe(" baz ");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[3][5].value).toBe("'");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/continuation1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# not a docstring\na = \\\nr'''\n>>> print(42)\na[wer]\n'''\n\nb = \\\n# docstring\nr'''\n>>> print()\na[wer]\n'''")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" not a docstring");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("\\");
+      expect(tokens[1][4].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][5].value).toBe("");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("r");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[2][1].value).toBe("'''");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][0].value).toBe(">>> print");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][1].value).toBe("(");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[3][2].value).toBe("42");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][3].value).toBe(")");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[4][0].value).toBe("a");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[4][1].value).toBe("[");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[4][2].value).toBe("w");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[4][3].value).toBe("e");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[4][4].value).toBe("r");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[4][5].value).toBe("]");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[5][0].value).toBe("'''");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][0].value).toBe("");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][0].value).toBe("b");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe(" ");
+      expect(tokens[7][1].scopes).toEqual(["source.python"]);
+      expect(tokens[7][2].value).toBe("=");
+      expect(tokens[7][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[7][3].value).toBe(" ");
+      expect(tokens[7][3].scopes).toEqual(["source.python"]);
+      expect(tokens[7][4].value).toBe("\\");
+      expect(tokens[7][4].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[7][5].value).toBe("");
+      expect(tokens[7][5].scopes).toEqual(["source.python"]);
+      expect(tokens[8][0].value).toBe("#");
+      expect(tokens[8][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[8][1].value).toBe(" docstring");
+      expect(tokens[8][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[9][0].value).toBe("r");
+      expect(tokens[9][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[9][1].value).toBe("'''");
+      expect(tokens[9][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][0].value).toBe(">>> ");
+      expect(tokens[10][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","keyword.control.flow.python"]);
+      expect(tokens[10][1].value).toBe("print()");
+      expect(tokens[10][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[11][0].value).toBe("a[wer]");
+      expect(tokens[11][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[12][0].value).toBe("'''");
+      expect(tokens[12][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/continuation2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("'\n'")
+      expect(tokens[0][0].value).toBe("'");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe("");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[1][0].value).toBe("'");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][1].value).toBe("");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","invalid.illegal.newline.python"]);
+    });
+
+  it("test/docstrings/continuation3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# not a docstring\na = \\\nr'>>> print(42)a[wer]'\n\nb = \\\n# docstring\nr'>>> print()a[wer]'")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" not a docstring");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("\\");
+      expect(tokens[1][4].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][5].value).toBe("");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("r");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[2][1].value).toBe("'");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe(">>> print");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[2][4].value).toBe("42");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[2][5].value).toBe(")");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[2][6].value).toBe("a");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[2][7].value).toBe("[");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[2][8].value).toBe("w");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[2][9].value).toBe("e");
+      expect(tokens[2][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[2][10].value).toBe("r");
+      expect(tokens[2][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[2][11].value).toBe("]");
+      expect(tokens[2][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[2][12].value).toBe("'");
+      expect(tokens[2][12].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("b");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("=");
+      expect(tokens[4][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][3].value).toBe(" ");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe("\\");
+      expect(tokens[4][4].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[4][5].value).toBe("");
+      expect(tokens[4][5].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("#");
+      expect(tokens[5][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[5][1].value).toBe(" docstring");
+      expect(tokens[5][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[6][0].value).toBe("r");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","storage.type.string.python"]);
+      expect(tokens[6][1].value).toBe("'");
+      expect(tokens[6][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][2].value).toBe(">>> print()a[wer]");
+      expect(tokens[6][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[6][3].value).toBe("'");
+      expect(tokens[6][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/continuation4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("    # not a docstring\n    a = \\\n    r'''\n    >>> print(42)\n    a[wer]\n    '''\n\n    b = \\\n    # docstring\n    r'''\n    >>> print()\n    a[wer]\n    '''")
+      expect(tokens[0][0].value).toBe("    ");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe("#");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][2].value).toBe(" not a docstring");
+      expect(tokens[0][2].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("a");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("=");
+      expect(tokens[1][3].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][4].value).toBe(" ");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][5].value).toBe("\\");
+      expect(tokens[1][5].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][6].value).toBe("");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("r");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[2][2].value).toBe("'''");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][0].value).toBe("    >>> print");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][1].value).toBe("(");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[3][2].value).toBe("42");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][3].value).toBe(")");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[4][0].value).toBe("    a");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[4][1].value).toBe("[");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[4][2].value).toBe("w");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[4][3].value).toBe("e");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[4][4].value).toBe("r");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[4][5].value).toBe("]");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[5][1].value).toBe("'''");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][0].value).toBe("");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("b");
+      expect(tokens[7][1].scopes).toEqual(["source.python"]);
+      expect(tokens[7][2].value).toBe(" ");
+      expect(tokens[7][2].scopes).toEqual(["source.python"]);
+      expect(tokens[7][3].value).toBe("=");
+      expect(tokens[7][3].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[7][4].value).toBe(" ");
+      expect(tokens[7][4].scopes).toEqual(["source.python"]);
+      expect(tokens[7][5].value).toBe("\\");
+      expect(tokens[7][5].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[7][6].value).toBe("");
+      expect(tokens[7][6].scopes).toEqual(["source.python"]);
+      expect(tokens[8][0].value).toBe("    ");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe("#");
+      expect(tokens[8][1].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[8][2].value).toBe(" docstring");
+      expect(tokens[8][2].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[9][0].value).toBe("    ");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].value).toBe("r");
+      expect(tokens[9][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[9][2].value).toBe("'''");
+      expect(tokens[9][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][0].value).toBe("    ");
+      expect(tokens[10][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[10][1].value).toBe(">>> ");
+      expect(tokens[10][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","keyword.control.flow.python"]);
+      expect(tokens[10][2].value).toBe("print()");
+      expect(tokens[10][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[11][0].value).toBe("    a[wer]");
+      expect(tokens[11][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[12][0].value).toBe("    ");
+      expect(tokens[12][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[12][1].value).toBe("'''");
+      expect(tokens[12][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/def1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def foo():\n    '''TE\\'''ST'''\n\ndef foo():\n    r'''TE\\'''ST'''\n\ndef foo():\n    R'''TE\\'''ST'''\n\ndef foo():\n    u'''TEST'''\n\ndef foo():\n    U'''TEST'''\n\ndef foo():\n    b'''TEST'''\n\ndef foo():\n    B'''TEST'''")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("'''");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("TE");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[1][3].value).toBe("\\'");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[1][4].value).toBe("''ST");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[1][5].value).toBe("'''");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("def");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[3][2].value).toBe("foo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[3][3].value).toBe("(");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[3][4].value).toBe(")");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[3][5].value).toBe(":");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("r");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[4][2].value).toBe("'''");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][3].value).toBe("TE");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][4].value).toBe("\\'");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][5].value).toBe("''ST");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][6].value).toBe("'''");
+      expect(tokens[4][6].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("def");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][2].value).toBe("foo");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[6][3].value).toBe("(");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[6][4].value).toBe(")");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[6][5].value).toBe(":");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("R");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[7][2].value).toBe("'''");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][3].value).toBe("TE");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[7][4].value).toBe("\\'");
+      expect(tokens[7][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[7][5].value).toBe("''ST");
+      expect(tokens[7][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[7][6].value).toBe("'''");
+      expect(tokens[7][6].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][0].value).toBe("def");
+      expect(tokens[9][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[9][1].value).toBe(" ");
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[9][2].value).toBe("foo");
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[9][3].value).toBe("(");
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[9][4].value).toBe(")");
+      expect(tokens[9][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[9][5].value).toBe(":");
+      expect(tokens[9][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[10][0].value).toBe("    ");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe("u");
+      expect(tokens[10][1].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[10][2].value).toBe("'''");
+      expect(tokens[10][2].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][3].value).toBe("TEST");
+      expect(tokens[10][3].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[10][4].value).toBe("'''");
+      expect(tokens[10][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[11][0].value).toBe("");
+      expect(tokens[11][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][0].value).toBe("def");
+      expect(tokens[12][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[12][1].value).toBe(" ");
+      expect(tokens[12][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[12][2].value).toBe("foo");
+      expect(tokens[12][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[12][3].value).toBe("(");
+      expect(tokens[12][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[12][4].value).toBe(")");
+      expect(tokens[12][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[12][5].value).toBe(":");
+      expect(tokens[12][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[13][0].value).toBe("    ");
+      expect(tokens[13][0].scopes).toEqual(["source.python"]);
+      expect(tokens[13][1].value).toBe("U");
+      expect(tokens[13][1].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[13][2].value).toBe("'''");
+      expect(tokens[13][2].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[13][3].value).toBe("TEST");
+      expect(tokens[13][3].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[13][4].value).toBe("'''");
+      expect(tokens[13][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[14][0].value).toBe("");
+      expect(tokens[14][0].scopes).toEqual(["source.python"]);
+      expect(tokens[15][0].value).toBe("def");
+      expect(tokens[15][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[15][1].value).toBe(" ");
+      expect(tokens[15][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[15][2].value).toBe("foo");
+      expect(tokens[15][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[15][3].value).toBe("(");
+      expect(tokens[15][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[15][4].value).toBe(")");
+      expect(tokens[15][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[15][5].value).toBe(":");
+      expect(tokens[15][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[16][0].value).toBe("    ");
+      expect(tokens[16][0].scopes).toEqual(["source.python"]);
+      expect(tokens[16][1].value).toBe("b");
+      expect(tokens[16][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[16][2].value).toBe("'''");
+      expect(tokens[16][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[16][3].value).toBe("TEST");
+      expect(tokens[16][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[16][4].value).toBe("'''");
+      expect(tokens[16][4].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[17][0].value).toBe("");
+      expect(tokens[17][0].scopes).toEqual(["source.python"]);
+      expect(tokens[18][0].value).toBe("def");
+      expect(tokens[18][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[18][1].value).toBe(" ");
+      expect(tokens[18][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[18][2].value).toBe("foo");
+      expect(tokens[18][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[18][3].value).toBe("(");
+      expect(tokens[18][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[18][4].value).toBe(")");
+      expect(tokens[18][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[18][5].value).toBe(":");
+      expect(tokens[18][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[19][0].value).toBe("    ");
+      expect(tokens[19][0].scopes).toEqual(["source.python"]);
+      expect(tokens[19][1].value).toBe("B");
+      expect(tokens[19][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[19][2].value).toBe("'''");
+      expect(tokens[19][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[19][3].value).toBe("TEST");
+      expect(tokens[19][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[19][4].value).toBe("'''");
+      expect(tokens[19][4].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/def2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def foo():\n    \"\"\"TE\\\"\"\"ST\"\"\"\n\ndef foo():\n    r\"\"\"TE\\\"\"\"ST\"\"\"\n\ndef foo():\n    R\"\"\"TE\\\"\"\"ST\"\"\"\n\ndef foo():\n    u\"\"\"TEST\"\"\"\n\ndef foo():\n    U\"\"\"TEST\"\"\"\n\ndef foo():\n    b\"\"\"TEST\"\"\"\n\ndef foo():\n    B\"\"\"TEST\"\"\"")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("\"\"\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("TE");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[1][3].value).toBe("\\\"");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[1][4].value).toBe("\"\"ST");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[1][5].value).toBe("\"\"\"");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("def");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[3][2].value).toBe("foo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[3][3].value).toBe("(");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[3][4].value).toBe(")");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[3][5].value).toBe(":");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("r");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[4][2].value).toBe("\"\"\"");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][3].value).toBe("TE");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][4].value).toBe("\\\"");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][5].value).toBe("\"\"ST");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][6].value).toBe("\"\"\"");
+      expect(tokens[4][6].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("def");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][2].value).toBe("foo");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[6][3].value).toBe("(");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[6][4].value).toBe(")");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[6][5].value).toBe(":");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("R");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[7][2].value).toBe("\"\"\"");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][3].value).toBe("TE");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[7][4].value).toBe("\\\"");
+      expect(tokens[7][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[7][5].value).toBe("\"\"ST");
+      expect(tokens[7][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[7][6].value).toBe("\"\"\"");
+      expect(tokens[7][6].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][0].value).toBe("def");
+      expect(tokens[9][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[9][1].value).toBe(" ");
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[9][2].value).toBe("foo");
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[9][3].value).toBe("(");
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[9][4].value).toBe(")");
+      expect(tokens[9][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[9][5].value).toBe(":");
+      expect(tokens[9][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[10][0].value).toBe("    ");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe("u");
+      expect(tokens[10][1].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[10][2].value).toBe("\"\"\"");
+      expect(tokens[10][2].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][3].value).toBe("TEST");
+      expect(tokens[10][3].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[10][4].value).toBe("\"\"\"");
+      expect(tokens[10][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[11][0].value).toBe("");
+      expect(tokens[11][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][0].value).toBe("def");
+      expect(tokens[12][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[12][1].value).toBe(" ");
+      expect(tokens[12][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[12][2].value).toBe("foo");
+      expect(tokens[12][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[12][3].value).toBe("(");
+      expect(tokens[12][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[12][4].value).toBe(")");
+      expect(tokens[12][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[12][5].value).toBe(":");
+      expect(tokens[12][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[13][0].value).toBe("    ");
+      expect(tokens[13][0].scopes).toEqual(["source.python"]);
+      expect(tokens[13][1].value).toBe("U");
+      expect(tokens[13][1].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[13][2].value).toBe("\"\"\"");
+      expect(tokens[13][2].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[13][3].value).toBe("TEST");
+      expect(tokens[13][3].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[13][4].value).toBe("\"\"\"");
+      expect(tokens[13][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[14][0].value).toBe("");
+      expect(tokens[14][0].scopes).toEqual(["source.python"]);
+      expect(tokens[15][0].value).toBe("def");
+      expect(tokens[15][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[15][1].value).toBe(" ");
+      expect(tokens[15][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[15][2].value).toBe("foo");
+      expect(tokens[15][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[15][3].value).toBe("(");
+      expect(tokens[15][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[15][4].value).toBe(")");
+      expect(tokens[15][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[15][5].value).toBe(":");
+      expect(tokens[15][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[16][0].value).toBe("    ");
+      expect(tokens[16][0].scopes).toEqual(["source.python"]);
+      expect(tokens[16][1].value).toBe("b");
+      expect(tokens[16][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[16][2].value).toBe("\"\"\"");
+      expect(tokens[16][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[16][3].value).toBe("TEST");
+      expect(tokens[16][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[16][4].value).toBe("\"\"\"");
+      expect(tokens[16][4].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[17][0].value).toBe("");
+      expect(tokens[17][0].scopes).toEqual(["source.python"]);
+      expect(tokens[18][0].value).toBe("def");
+      expect(tokens[18][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[18][1].value).toBe(" ");
+      expect(tokens[18][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[18][2].value).toBe("foo");
+      expect(tokens[18][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[18][3].value).toBe("(");
+      expect(tokens[18][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[18][4].value).toBe(")");
+      expect(tokens[18][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[18][5].value).toBe(":");
+      expect(tokens[18][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[19][0].value).toBe("    ");
+      expect(tokens[19][0].scopes).toEqual(["source.python"]);
+      expect(tokens[19][1].value).toBe("B");
+      expect(tokens[19][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[19][2].value).toBe("\"\"\"");
+      expect(tokens[19][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[19][3].value).toBe("TEST");
+      expect(tokens[19][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[19][4].value).toBe("\"\"\"");
+      expect(tokens[19][4].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/def3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def foo():\n    'TE\\'ST'\n\ndef foo():\n    r'TE\\'ST'\n\ndef foo():\n    R'TE\\'ST'\n\ndef foo():\n    u'TEST'\n\ndef foo():\n    U'TEST'\n\ndef foo():\n    b'TEST'\n\ndef foo():\n    B'TEST'")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("'");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("TE");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[1][3].value).toBe("\\'");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.single.python","constant.character.escape.python"]);
+      expect(tokens[1][4].value).toBe("ST");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("def");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[3][2].value).toBe("foo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[3][3].value).toBe("(");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[3][4].value).toBe(")");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[3][5].value).toBe(":");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("r");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","storage.type.string.python"]);
+      expect(tokens[4][2].value).toBe("'");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][3].value).toBe("TE");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[4][4].value).toBe("\\'");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[4][5].value).toBe("ST");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[4][6].value).toBe("'");
+      expect(tokens[4][6].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("def");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][2].value).toBe("foo");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[6][3].value).toBe("(");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[6][4].value).toBe(")");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[6][5].value).toBe(":");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("R");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","storage.type.string.python"]);
+      expect(tokens[7][2].value).toBe("'");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][3].value).toBe("TE");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[7][4].value).toBe("\\'");
+      expect(tokens[7][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[7][5].value).toBe("ST");
+      expect(tokens[7][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[7][6].value).toBe("'");
+      expect(tokens[7][6].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][0].value).toBe("def");
+      expect(tokens[9][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[9][1].value).toBe(" ");
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[9][2].value).toBe("foo");
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[9][3].value).toBe("(");
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[9][4].value).toBe(")");
+      expect(tokens[9][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[9][5].value).toBe(":");
+      expect(tokens[9][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[10][0].value).toBe("    ");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe("u");
+      expect(tokens[10][1].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[10][2].value).toBe("'");
+      expect(tokens[10][2].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][3].value).toBe("TEST");
+      expect(tokens[10][3].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[10][4].value).toBe("'");
+      expect(tokens[10][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[11][0].value).toBe("");
+      expect(tokens[11][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][0].value).toBe("def");
+      expect(tokens[12][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[12][1].value).toBe(" ");
+      expect(tokens[12][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[12][2].value).toBe("foo");
+      expect(tokens[12][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[12][3].value).toBe("(");
+      expect(tokens[12][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[12][4].value).toBe(")");
+      expect(tokens[12][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[12][5].value).toBe(":");
+      expect(tokens[12][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[13][0].value).toBe("    ");
+      expect(tokens[13][0].scopes).toEqual(["source.python"]);
+      expect(tokens[13][1].value).toBe("U");
+      expect(tokens[13][1].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[13][2].value).toBe("'");
+      expect(tokens[13][2].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[13][3].value).toBe("TEST");
+      expect(tokens[13][3].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[13][4].value).toBe("'");
+      expect(tokens[13][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[14][0].value).toBe("");
+      expect(tokens[14][0].scopes).toEqual(["source.python"]);
+      expect(tokens[15][0].value).toBe("def");
+      expect(tokens[15][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[15][1].value).toBe(" ");
+      expect(tokens[15][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[15][2].value).toBe("foo");
+      expect(tokens[15][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[15][3].value).toBe("(");
+      expect(tokens[15][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[15][4].value).toBe(")");
+      expect(tokens[15][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[15][5].value).toBe(":");
+      expect(tokens[15][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[16][0].value).toBe("    ");
+      expect(tokens[16][0].scopes).toEqual(["source.python"]);
+      expect(tokens[16][1].value).toBe("b");
+      expect(tokens[16][1].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[16][2].value).toBe("'");
+      expect(tokens[16][2].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[16][3].value).toBe("TEST");
+      expect(tokens[16][3].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[16][4].value).toBe("'");
+      expect(tokens[16][4].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[17][0].value).toBe("");
+      expect(tokens[17][0].scopes).toEqual(["source.python"]);
+      expect(tokens[18][0].value).toBe("def");
+      expect(tokens[18][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[18][1].value).toBe(" ");
+      expect(tokens[18][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[18][2].value).toBe("foo");
+      expect(tokens[18][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[18][3].value).toBe("(");
+      expect(tokens[18][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[18][4].value).toBe(")");
+      expect(tokens[18][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[18][5].value).toBe(":");
+      expect(tokens[18][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[19][0].value).toBe("    ");
+      expect(tokens[19][0].scopes).toEqual(["source.python"]);
+      expect(tokens[19][1].value).toBe("B");
+      expect(tokens[19][1].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[19][2].value).toBe("'");
+      expect(tokens[19][2].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[19][3].value).toBe("TEST");
+      expect(tokens[19][3].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[19][4].value).toBe("'");
+      expect(tokens[19][4].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/def4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def foo():\n    \"TE\\\"ST\"\n\ndef foo():\n    r\"TE\\\"ST\"\n\ndef foo():\n    R\"TE\\\"ST\"\n\ndef foo():\n    u\"TEST\"\n\ndef foo():\n    U\"TEST\"\n\ndef foo():\n    b\"TEST\"\n\ndef foo():\n    B\"TEST\"")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("TE");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[1][3].value).toBe("\\\"");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.single.python","constant.character.escape.python"]);
+      expect(tokens[1][4].value).toBe("ST");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[1][5].value).toBe("\"");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("def");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[3][2].value).toBe("foo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[3][3].value).toBe("(");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[3][4].value).toBe(")");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[3][5].value).toBe(":");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("r");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","storage.type.string.python"]);
+      expect(tokens[4][2].value).toBe("\"");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][3].value).toBe("TE");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[4][4].value).toBe("\\\"");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[4][5].value).toBe("ST");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[4][6].value).toBe("\"");
+      expect(tokens[4][6].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("def");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][2].value).toBe("foo");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[6][3].value).toBe("(");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[6][4].value).toBe(")");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[6][5].value).toBe(":");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("R");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","storage.type.string.python"]);
+      expect(tokens[7][2].value).toBe("\"");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][3].value).toBe("TE");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[7][4].value).toBe("\\\"");
+      expect(tokens[7][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[7][5].value).toBe("ST");
+      expect(tokens[7][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[7][6].value).toBe("\"");
+      expect(tokens[7][6].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][0].value).toBe("def");
+      expect(tokens[9][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[9][1].value).toBe(" ");
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[9][2].value).toBe("foo");
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[9][3].value).toBe("(");
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[9][4].value).toBe(")");
+      expect(tokens[9][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[9][5].value).toBe(":");
+      expect(tokens[9][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[10][0].value).toBe("    ");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe("u");
+      expect(tokens[10][1].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[10][2].value).toBe("\"");
+      expect(tokens[10][2].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][3].value).toBe("TEST");
+      expect(tokens[10][3].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[10][4].value).toBe("\"");
+      expect(tokens[10][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[11][0].value).toBe("");
+      expect(tokens[11][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][0].value).toBe("def");
+      expect(tokens[12][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[12][1].value).toBe(" ");
+      expect(tokens[12][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[12][2].value).toBe("foo");
+      expect(tokens[12][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[12][3].value).toBe("(");
+      expect(tokens[12][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[12][4].value).toBe(")");
+      expect(tokens[12][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[12][5].value).toBe(":");
+      expect(tokens[12][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[13][0].value).toBe("    ");
+      expect(tokens[13][0].scopes).toEqual(["source.python"]);
+      expect(tokens[13][1].value).toBe("U");
+      expect(tokens[13][1].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[13][2].value).toBe("\"");
+      expect(tokens[13][2].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[13][3].value).toBe("TEST");
+      expect(tokens[13][3].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[13][4].value).toBe("\"");
+      expect(tokens[13][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[14][0].value).toBe("");
+      expect(tokens[14][0].scopes).toEqual(["source.python"]);
+      expect(tokens[15][0].value).toBe("def");
+      expect(tokens[15][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[15][1].value).toBe(" ");
+      expect(tokens[15][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[15][2].value).toBe("foo");
+      expect(tokens[15][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[15][3].value).toBe("(");
+      expect(tokens[15][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[15][4].value).toBe(")");
+      expect(tokens[15][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[15][5].value).toBe(":");
+      expect(tokens[15][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[16][0].value).toBe("    ");
+      expect(tokens[16][0].scopes).toEqual(["source.python"]);
+      expect(tokens[16][1].value).toBe("b");
+      expect(tokens[16][1].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[16][2].value).toBe("\"");
+      expect(tokens[16][2].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[16][3].value).toBe("TEST");
+      expect(tokens[16][3].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[16][4].value).toBe("\"");
+      expect(tokens[16][4].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[17][0].value).toBe("");
+      expect(tokens[17][0].scopes).toEqual(["source.python"]);
+      expect(tokens[18][0].value).toBe("def");
+      expect(tokens[18][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[18][1].value).toBe(" ");
+      expect(tokens[18][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[18][2].value).toBe("foo");
+      expect(tokens[18][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[18][3].value).toBe("(");
+      expect(tokens[18][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[18][4].value).toBe(")");
+      expect(tokens[18][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[18][5].value).toBe(":");
+      expect(tokens[18][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[19][0].value).toBe("    ");
+      expect(tokens[19][0].scopes).toEqual(["source.python"]);
+      expect(tokens[19][1].value).toBe("B");
+      expect(tokens[19][1].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[19][2].value).toBe("\"");
+      expect(tokens[19][2].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[19][3].value).toBe("TEST");
+      expect(tokens[19][3].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[19][4].value).toBe("\"");
+      expect(tokens[19][4].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/escaping1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("'''Module docstring\n\n    {{ %d simple \\\\ string \\\n    foo \\' \\\" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005\n\n    multiline \"unicode\" string \\\n    \\xf1 \\u1234aaaa \\U1234aaaa\n    \\N{BLACK SPADE SUIT}\n'''")
+      expect(tokens[0][0].value).toBe("'''");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe("Module docstring");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[2][0].value).toBe("    {{ %d simple ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[2][1].value).toBe("\\\\");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[2][2].value).toBe(" string ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[2][3].value).toBe("\\");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.language.python"]);
+      expect(tokens[3][0].value).toBe("    foo ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][1].value).toBe("\\'");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][3].value).toBe("\\\"");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][4].value).toBe(" ");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][5].value).toBe("\\a");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][6].value).toBe(" ");
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][7].value).toBe("\\b");
+      expect(tokens[3][7].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][8].value).toBe(" \\c ");
+      expect(tokens[3][8].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][9].value).toBe("\\f");
+      expect(tokens[3][9].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][10].value).toBe(" ");
+      expect(tokens[3][10].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][11].value).toBe("\\n");
+      expect(tokens[3][11].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][12].value).toBe(" ");
+      expect(tokens[3][12].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][13].value).toBe("\\r");
+      expect(tokens[3][13].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][14].value).toBe(" ");
+      expect(tokens[3][14].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][15].value).toBe("\\t");
+      expect(tokens[3][15].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][16].value).toBe(" ");
+      expect(tokens[3][16].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][17].value).toBe("\\v");
+      expect(tokens[3][17].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][18].value).toBe(" ");
+      expect(tokens[3][18].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][19].value).toBe("\\5");
+      expect(tokens[3][19].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][20].value).toBe(" ");
+      expect(tokens[3][20].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][21].value).toBe("\\55");
+      expect(tokens[3][21].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][22].value).toBe(" ");
+      expect(tokens[3][22].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][23].value).toBe("\\555");
+      expect(tokens[3][23].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][24].value).toBe(" ");
+      expect(tokens[3][24].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][25].value).toBe("\\05");
+      expect(tokens[3][25].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][26].value).toBe(" ");
+      expect(tokens[3][26].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][27].value).toBe("\\005");
+      expect(tokens[3][27].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[5][0].value).toBe("    multiline \"unicode\" string ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[5][1].value).toBe("\\");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.language.python"]);
+      expect(tokens[6][0].value).toBe("    ");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[6][1].value).toBe("\\xf1");
+      expect(tokens[6][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[6][2].value).toBe(" ");
+      expect(tokens[6][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[6][3].value).toBe("\\u1234");
+      expect(tokens[6][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[6][4].value).toBe("aaaa ");
+      expect(tokens[6][4].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[6][5].value).toBe("\\U1234aaaa");
+      expect(tokens[6][5].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[7][1].value).toBe("\\N{BLACK SPADE SUIT}");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[8][0].value).toBe("'''");
+      expect(tokens[8][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/escaping2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("r'''Module docstring\n\n    {{ %d simple \\\\ string \\\n    foo \\' \\\" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005\n\n    multiline \"unicode\" string \\\n    \\xf1 \\u1234aaaa \\U1234aaaa\n    \\N{BLACK SPADE SUIT}\n    >>> aaa\n'''\n\nR'''Module docstring\n\n    {{ %d simple \\\\ string \\\n    foo \\' \\\" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005\n\n    multiline \"unicode\" string \\\n    \\xf1 \\u1234aaaa \\U1234aaaa\n    \\N{BLACK SPADE SUIT}\n    >>> aaa\n'''")
+      expect(tokens[0][0].value).toBe("r");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[0][1].value).toBe("'''");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("Module docstring");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[2][0].value).toBe("    {{ %d simple ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[2][1].value).toBe("\\\\");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[2][2].value).toBe(" string ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[2][3].value).toBe("\\");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[3][0].value).toBe("    foo ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[3][1].value).toBe("\\'");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[3][3].value).toBe("\\\"");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[3][4].value).toBe(" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[5][0].value).toBe("    multiline \"unicode\" string ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[5][1].value).toBe("\\");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[6][0].value).toBe("    \\xf1 \\u1234aaaa \\U1234aaaa");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[7][0].value).toBe("    \\N{BLACK SPADE SUIT}");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[8][0].value).toBe("    ");
+      expect(tokens[8][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[8][1].value).toBe(">>> ");
+      expect(tokens[8][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","keyword.control.flow.python"]);
+      expect(tokens[8][2].value).toBe("aaa");
+      expect(tokens[8][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[9][0].value).toBe("'''");
+      expect(tokens[9][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[10][0].value).toBe("");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[11][0].value).toBe("R");
+      expect(tokens[11][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[11][1].value).toBe("'''");
+      expect(tokens[11][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[11][2].value).toBe("Module docstring");
+      expect(tokens[11][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[12][0].value).toBe("");
+      expect(tokens[12][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[13][0].value).toBe("    {{ %d simple ");
+      expect(tokens[13][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[13][1].value).toBe("\\\\");
+      expect(tokens[13][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[13][2].value).toBe(" string ");
+      expect(tokens[13][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[13][3].value).toBe("\\");
+      expect(tokens[13][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[14][0].value).toBe("    foo ");
+      expect(tokens[14][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[14][1].value).toBe("\\'");
+      expect(tokens[14][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[14][2].value).toBe(" ");
+      expect(tokens[14][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[14][3].value).toBe("\\\"");
+      expect(tokens[14][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[14][4].value).toBe(" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005");
+      expect(tokens[14][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[15][0].value).toBe("");
+      expect(tokens[15][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[16][0].value).toBe("    multiline \"unicode\" string ");
+      expect(tokens[16][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[16][1].value).toBe("\\");
+      expect(tokens[16][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[17][0].value).toBe("    \\xf1 \\u1234aaaa \\U1234aaaa");
+      expect(tokens[17][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[18][0].value).toBe("    \\N{BLACK SPADE SUIT}");
+      expect(tokens[18][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[19][0].value).toBe("    ");
+      expect(tokens[19][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[19][1].value).toBe(">>> ");
+      expect(tokens[19][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","keyword.control.flow.python"]);
+      expect(tokens[19][2].value).toBe("aaa");
+      expect(tokens[19][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[20][0].value).toBe("'''");
+      expect(tokens[20][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/escaping3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("r'''Module docstring\n\n    (?x)                # not a regexp\n        foo[20]{42}     # not a comment\n'''")
+      expect(tokens[0][0].value).toBe("r");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[0][1].value).toBe("'''");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("Module docstring");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[2][0].value).toBe("    (?x)                # not a regexp");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[3][0].value).toBe("        foo[20]{42}     # not a comment");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][0].value).toBe("'''");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/format1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("r'''Module docstring\n\n    %(language)s has %(number)03d quote types.\n'''")
+      expect(tokens[0][0].value).toBe("r");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[0][1].value).toBe("'''");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("Module docstring");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[2][0].value).toBe("    %(language)s has %(number)03d quote types.");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[3][0].value).toBe("'''");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/format2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("'''{foo}'''")
+      expect(tokens[0][0].value).toBe("'''");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe("{foo}");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[0][2].value).toBe("'''");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/mix1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("'''TEST'''\n\nclass Foo:\n    # comment\n    R'''TEST'''\n\n    def foo(self, a:'''TEST''') -> '''TEST''': #ok\n        r'''TEST'''\n        with bar:\n            pass\n\n    def bar(self, a:'''TEST''') -> '''TEST''': pass\n        '''TEST''' # additional docstring\n        with bar:\n            pass")
+      expect(tokens[0][0].value).toBe("'''");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe("TEST");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[0][2].value).toBe("'''");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("class");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[2][2].value).toBe("Foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[2][3].value).toBe(":");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("#");
+      expect(tokens[3][1].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][2].value).toBe(" comment");
+      expect(tokens[3][2].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("R");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[4][2].value).toBe("'''");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][3].value).toBe("TEST");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][4].value).toBe("'''");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("    ");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][1].value).toBe("def");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[6][2].value).toBe(" ");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][3].value).toBe("foo");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[6][4].value).toBe("(");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[6][5].value).toBe("self");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python","variable.parameter.function.language.special.self.python"]);
+      expect(tokens[6][6].value).toBe(",");
+      expect(tokens[6][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[6][7].value).toBe(" ");
+      expect(tokens[6][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[6][8].value).toBe("a");
+      expect(tokens[6][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[6][9].value).toBe(":");
+      expect(tokens[6][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.annotation.python"]);
+      expect(tokens[6][10].value).toBe("'''");
+      expect(tokens[6][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][11].value).toBe("TEST");
+      expect(tokens[6][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.multi.python"]);
+      expect(tokens[6][12].value).toBe("'''");
+      expect(tokens[6][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][13].value).toBe(")");
+      expect(tokens[6][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[6][14].value).toBe(" ");
+      expect(tokens[6][14].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][15].value).toBe("->");
+      expect(tokens[6][15].scopes).toEqual(["source.python","meta.function.python","punctuation.separator.annotation.result.python"]);
+      expect(tokens[6][16].value).toBe(" ");
+      expect(tokens[6][16].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][17].value).toBe("'''");
+      expect(tokens[6][17].scopes).toEqual(["source.python","meta.function.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][18].value).toBe("TEST");
+      expect(tokens[6][18].scopes).toEqual(["source.python","meta.function.python","string.quoted.multi.python"]);
+      expect(tokens[6][19].value).toBe("'''");
+      expect(tokens[6][19].scopes).toEqual(["source.python","meta.function.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][20].value).toBe(":");
+      expect(tokens[6][20].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[6][21].value).toBe(" ");
+      expect(tokens[6][21].scopes).toEqual(["source.python"]);
+      expect(tokens[6][22].value).toBe("#");
+      expect(tokens[6][22].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[6][23].value).toBe("ok");
+      expect(tokens[6][23].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[7][0].value).toBe("        ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("r");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[7][2].value).toBe("'''");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][3].value).toBe("TEST");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[7][4].value).toBe("'''");
+      expect(tokens[7][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("        ");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe("with");
+      expect(tokens[8][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[8][2].value).toBe(" ");
+      expect(tokens[8][2].scopes).toEqual(["source.python"]);
+      expect(tokens[8][3].value).toBe("bar");
+      expect(tokens[8][3].scopes).toEqual(["source.python"]);
+      expect(tokens[8][4].value).toBe(":");
+      expect(tokens[8][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[9][0].value).toBe("            ");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].value).toBe("pass");
+      expect(tokens[9][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[10][0].value).toBe("");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[11][0].value).toBe("    ");
+      expect(tokens[11][0].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[11][1].value).toBe("def");
+      expect(tokens[11][1].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[11][2].value).toBe(" ");
+      expect(tokens[11][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[11][3].value).toBe("bar");
+      expect(tokens[11][3].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[11][4].value).toBe("(");
+      expect(tokens[11][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[11][5].value).toBe("self");
+      expect(tokens[11][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python","variable.parameter.function.language.special.self.python"]);
+      expect(tokens[11][6].value).toBe(",");
+      expect(tokens[11][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[11][7].value).toBe(" ");
+      expect(tokens[11][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[11][8].value).toBe("a");
+      expect(tokens[11][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[11][9].value).toBe(":");
+      expect(tokens[11][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.annotation.python"]);
+      expect(tokens[11][10].value).toBe("'''");
+      expect(tokens[11][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[11][11].value).toBe("TEST");
+      expect(tokens[11][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.multi.python"]);
+      expect(tokens[11][12].value).toBe("'''");
+      expect(tokens[11][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[11][13].value).toBe(")");
+      expect(tokens[11][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[11][14].value).toBe(" ");
+      expect(tokens[11][14].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[11][15].value).toBe("->");
+      expect(tokens[11][15].scopes).toEqual(["source.python","meta.function.python","punctuation.separator.annotation.result.python"]);
+      expect(tokens[11][16].value).toBe(" ");
+      expect(tokens[11][16].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[11][17].value).toBe("'''");
+      expect(tokens[11][17].scopes).toEqual(["source.python","meta.function.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[11][18].value).toBe("TEST");
+      expect(tokens[11][18].scopes).toEqual(["source.python","meta.function.python","string.quoted.multi.python"]);
+      expect(tokens[11][19].value).toBe("'''");
+      expect(tokens[11][19].scopes).toEqual(["source.python","meta.function.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[11][20].value).toBe(":");
+      expect(tokens[11][20].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[11][21].value).toBe(" ");
+      expect(tokens[11][21].scopes).toEqual(["source.python"]);
+      expect(tokens[11][22].value).toBe("pass");
+      expect(tokens[11][22].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[12][0].value).toBe("        ");
+      expect(tokens[12][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][1].value).toBe("'''");
+      expect(tokens[12][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[12][2].value).toBe("TEST");
+      expect(tokens[12][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[12][3].value).toBe("'''");
+      expect(tokens[12][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[12][4].value).toBe(" ");
+      expect(tokens[12][4].scopes).toEqual(["source.python"]);
+      expect(tokens[12][5].value).toBe("#");
+      expect(tokens[12][5].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[12][6].value).toBe(" additional docstring");
+      expect(tokens[12][6].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[13][0].value).toBe("        ");
+      expect(tokens[13][0].scopes).toEqual(["source.python"]);
+      expect(tokens[13][1].value).toBe("with");
+      expect(tokens[13][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[13][2].value).toBe(" ");
+      expect(tokens[13][2].scopes).toEqual(["source.python"]);
+      expect(tokens[13][3].value).toBe("bar");
+      expect(tokens[13][3].scopes).toEqual(["source.python"]);
+      expect(tokens[13][4].value).toBe(":");
+      expect(tokens[13][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[14][0].value).toBe("            ");
+      expect(tokens[14][0].scopes).toEqual(["source.python"]);
+      expect(tokens[14][1].value).toBe("pass");
+      expect(tokens[14][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/docstrings/mix2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("'TEST'\n\nclass Foo:\n    # comment\n    R'TEST'\n\n    def foo(self, a:'TEST') -> 'TEST': #ok\n        r'TEST'\n        with bar:\n            pass\n\n    def bar(self, a:'TEST') -> 'TEST': pass\n        'TEST' # additional docstring\n        with bar:\n            pass")
+      expect(tokens[0][0].value).toBe("'");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe("TEST");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[0][2].value).toBe("'");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("class");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[2][2].value).toBe("Foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[2][3].value).toBe(":");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("#");
+      expect(tokens[3][1].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][2].value).toBe(" comment");
+      expect(tokens[3][2].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("R");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","storage.type.string.python"]);
+      expect(tokens[4][2].value).toBe("'");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][3].value).toBe("TEST");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[4][4].value).toBe("'");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("    ");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][1].value).toBe("def");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[6][2].value).toBe(" ");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][3].value).toBe("foo");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[6][4].value).toBe("(");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[6][5].value).toBe("self");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python","variable.parameter.function.language.special.self.python"]);
+      expect(tokens[6][6].value).toBe(",");
+      expect(tokens[6][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[6][7].value).toBe(" ");
+      expect(tokens[6][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[6][8].value).toBe("a");
+      expect(tokens[6][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[6][9].value).toBe(":");
+      expect(tokens[6][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.annotation.python"]);
+      expect(tokens[6][10].value).toBe("'");
+      expect(tokens[6][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][11].value).toBe("TEST");
+      expect(tokens[6][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python"]);
+      expect(tokens[6][12].value).toBe("'");
+      expect(tokens[6][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][13].value).toBe(")");
+      expect(tokens[6][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[6][14].value).toBe(" ");
+      expect(tokens[6][14].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][15].value).toBe("->");
+      expect(tokens[6][15].scopes).toEqual(["source.python","meta.function.python","punctuation.separator.annotation.result.python"]);
+      expect(tokens[6][16].value).toBe(" ");
+      expect(tokens[6][16].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][17].value).toBe("'");
+      expect(tokens[6][17].scopes).toEqual(["source.python","meta.function.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][18].value).toBe("TEST");
+      expect(tokens[6][18].scopes).toEqual(["source.python","meta.function.python","string.quoted.single.python"]);
+      expect(tokens[6][19].value).toBe("'");
+      expect(tokens[6][19].scopes).toEqual(["source.python","meta.function.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][20].value).toBe(":");
+      expect(tokens[6][20].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[6][21].value).toBe(" ");
+      expect(tokens[6][21].scopes).toEqual(["source.python"]);
+      expect(tokens[6][22].value).toBe("#");
+      expect(tokens[6][22].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[6][23].value).toBe("ok");
+      expect(tokens[6][23].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[7][0].value).toBe("        ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("r");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","storage.type.string.python"]);
+      expect(tokens[7][2].value).toBe("'");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][3].value).toBe("TEST");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[7][4].value).toBe("'");
+      expect(tokens[7][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("        ");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe("with");
+      expect(tokens[8][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[8][2].value).toBe(" ");
+      expect(tokens[8][2].scopes).toEqual(["source.python"]);
+      expect(tokens[8][3].value).toBe("bar");
+      expect(tokens[8][3].scopes).toEqual(["source.python"]);
+      expect(tokens[8][4].value).toBe(":");
+      expect(tokens[8][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[9][0].value).toBe("            ");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].value).toBe("pass");
+      expect(tokens[9][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[10][0].value).toBe("");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[11][0].value).toBe("    ");
+      expect(tokens[11][0].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[11][1].value).toBe("def");
+      expect(tokens[11][1].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[11][2].value).toBe(" ");
+      expect(tokens[11][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[11][3].value).toBe("bar");
+      expect(tokens[11][3].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[11][4].value).toBe("(");
+      expect(tokens[11][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[11][5].value).toBe("self");
+      expect(tokens[11][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python","variable.parameter.function.language.special.self.python"]);
+      expect(tokens[11][6].value).toBe(",");
+      expect(tokens[11][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[11][7].value).toBe(" ");
+      expect(tokens[11][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[11][8].value).toBe("a");
+      expect(tokens[11][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[11][9].value).toBe(":");
+      expect(tokens[11][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.annotation.python"]);
+      expect(tokens[11][10].value).toBe("'");
+      expect(tokens[11][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[11][11].value).toBe("TEST");
+      expect(tokens[11][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python"]);
+      expect(tokens[11][12].value).toBe("'");
+      expect(tokens[11][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[11][13].value).toBe(")");
+      expect(tokens[11][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[11][14].value).toBe(" ");
+      expect(tokens[11][14].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[11][15].value).toBe("->");
+      expect(tokens[11][15].scopes).toEqual(["source.python","meta.function.python","punctuation.separator.annotation.result.python"]);
+      expect(tokens[11][16].value).toBe(" ");
+      expect(tokens[11][16].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[11][17].value).toBe("'");
+      expect(tokens[11][17].scopes).toEqual(["source.python","meta.function.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[11][18].value).toBe("TEST");
+      expect(tokens[11][18].scopes).toEqual(["source.python","meta.function.python","string.quoted.single.python"]);
+      expect(tokens[11][19].value).toBe("'");
+      expect(tokens[11][19].scopes).toEqual(["source.python","meta.function.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[11][20].value).toBe(":");
+      expect(tokens[11][20].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[11][21].value).toBe(" ");
+      expect(tokens[11][21].scopes).toEqual(["source.python"]);
+      expect(tokens[11][22].value).toBe("pass");
+      expect(tokens[11][22].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[12][0].value).toBe("        ");
+      expect(tokens[12][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][1].value).toBe("'");
+      expect(tokens[12][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[12][2].value).toBe("TEST");
+      expect(tokens[12][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[12][3].value).toBe("'");
+      expect(tokens[12][3].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[12][4].value).toBe(" ");
+      expect(tokens[12][4].scopes).toEqual(["source.python"]);
+      expect(tokens[12][5].value).toBe("#");
+      expect(tokens[12][5].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[12][6].value).toBe(" additional docstring");
+      expect(tokens[12][6].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[13][0].value).toBe("        ");
+      expect(tokens[13][0].scopes).toEqual(["source.python"]);
+      expect(tokens[13][1].value).toBe("with");
+      expect(tokens[13][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[13][2].value).toBe(" ");
+      expect(tokens[13][2].scopes).toEqual(["source.python"]);
+      expect(tokens[13][3].value).toBe("bar");
+      expect(tokens[13][3].scopes).toEqual(["source.python"]);
+      expect(tokens[13][4].value).toBe(":");
+      expect(tokens[13][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[14][0].value).toBe("            ");
+      expect(tokens[14][0].scopes).toEqual(["source.python"]);
+      expect(tokens[14][1].value).toBe("pass");
+      expect(tokens[14][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/docstrings/module1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("'''TEST'''\nr'''TEST'''\nR'''TEST'''\n\nu'''TEST'''\nU'''TEST'''\nb'''TEST'''\nB'''TEST'''")
+      expect(tokens[0][0].value).toBe("'''");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe("TEST");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[0][2].value).toBe("'''");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("r");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[1][1].value).toBe("'''");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("TEST");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[1][3].value).toBe("'''");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("R");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[2][1].value).toBe("'''");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("TEST");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[2][3].value).toBe("'''");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("u");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[4][1].value).toBe("'''");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][2].value).toBe("TEST");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[4][3].value).toBe("'''");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("U");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[5][1].value).toBe("'''");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][2].value).toBe("TEST");
+      expect(tokens[5][2].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[5][3].value).toBe("'''");
+      expect(tokens[5][3].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][0].value).toBe("b");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[6][1].value).toBe("'''");
+      expect(tokens[6][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][2].value).toBe("TEST");
+      expect(tokens[6][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[6][3].value).toBe("'''");
+      expect(tokens[6][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[7][0].value).toBe("B");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[7][1].value).toBe("'''");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][2].value).toBe("TEST");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[7][3].value).toBe("'''");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/module2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("\"\"\"TEST\"\"\"\nr\"\"\"TEST\"\"\"\nR\"\"\"TEST\"\"\"\n\nu\"\"\"TEST\"\"\"\nU\"\"\"TEST\"\"\"\nb\"\"\"TEST\"\"\"\nB\"\"\"TEST\"\"\"")
+      expect(tokens[0][0].value).toBe("\"\"\"");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe("TEST");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[0][2].value).toBe("\"\"\"");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("r");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[1][1].value).toBe("\"\"\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("TEST");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[1][3].value).toBe("\"\"\"");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("R");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[2][1].value).toBe("\"\"\"");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("TEST");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[2][3].value).toBe("\"\"\"");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("u");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[4][1].value).toBe("\"\"\"");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][2].value).toBe("TEST");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[4][3].value).toBe("\"\"\"");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("U");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[5][1].value).toBe("\"\"\"");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][2].value).toBe("TEST");
+      expect(tokens[5][2].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[5][3].value).toBe("\"\"\"");
+      expect(tokens[5][3].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][0].value).toBe("b");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[6][1].value).toBe("\"\"\"");
+      expect(tokens[6][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][2].value).toBe("TEST");
+      expect(tokens[6][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[6][3].value).toBe("\"\"\"");
+      expect(tokens[6][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[7][0].value).toBe("B");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[7][1].value).toBe("\"\"\"");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][2].value).toBe("TEST");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[7][3].value).toBe("\"\"\"");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/module3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("'TE\\'ST'\nr'TE\\'ST'\nR'TE\\'ST'\n\nu'TEST'\nU'TEST'\nb'TEST'\nB'TEST'")
+      expect(tokens[0][0].value).toBe("'");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe("TE");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[0][2].value).toBe("\\'");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python","constant.character.escape.python"]);
+      expect(tokens[0][3].value).toBe("ST");
+      expect(tokens[0][3].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("r");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","storage.type.string.python"]);
+      expect(tokens[1][1].value).toBe("'");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("TE");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[1][3].value).toBe("\\'");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[1][4].value).toBe("ST");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("R");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","storage.type.string.python"]);
+      expect(tokens[2][1].value).toBe("'");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("TE");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[2][3].value).toBe("\\'");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[2][4].value).toBe("ST");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("u");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[4][1].value).toBe("'");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][2].value).toBe("TEST");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[4][3].value).toBe("'");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("U");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[5][1].value).toBe("'");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][2].value).toBe("TEST");
+      expect(tokens[5][2].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[5][3].value).toBe("'");
+      expect(tokens[5][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][0].value).toBe("b");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[6][1].value).toBe("'");
+      expect(tokens[6][1].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][2].value).toBe("TEST");
+      expect(tokens[6][2].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[6][3].value).toBe("'");
+      expect(tokens[6][3].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[7][0].value).toBe("B");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[7][1].value).toBe("'");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][2].value).toBe("TEST");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[7][3].value).toBe("'");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/module4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("\"TE\\\"ST\"\nr\"TE\\\"ST\"\nR\"TE\\\"ST\"\n\nu\"TEST\"\nU\"TEST\"\nb\"TEST\"\nB\"TEST\"")
+      expect(tokens[0][0].value).toBe("\"");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe("TE");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[0][2].value).toBe("\\\"");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python","constant.character.escape.python"]);
+      expect(tokens[0][3].value).toBe("ST");
+      expect(tokens[0][3].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[0][4].value).toBe("\"");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("r");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","storage.type.string.python"]);
+      expect(tokens[1][1].value).toBe("\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("TE");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[1][3].value).toBe("\\\"");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[1][4].value).toBe("ST");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[1][5].value).toBe("\"");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("R");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","storage.type.string.python"]);
+      expect(tokens[2][1].value).toBe("\"");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("TE");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[2][3].value).toBe("\\\"");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[2][4].value).toBe("ST");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python"]);
+      expect(tokens[2][5].value).toBe("\"");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.docstring.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("u");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[4][1].value).toBe("\"");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][2].value).toBe("TEST");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[4][3].value).toBe("\"");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("U");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[5][1].value).toBe("\"");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][2].value).toBe("TEST");
+      expect(tokens[5][2].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[5][3].value).toBe("\"");
+      expect(tokens[5][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][0].value).toBe("b");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[6][1].value).toBe("\"");
+      expect(tokens[6][1].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][2].value).toBe("TEST");
+      expect(tokens[6][2].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[6][3].value).toBe("\"");
+      expect(tokens[6][3].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[7][0].value).toBe("B");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[7][1].value).toBe("\"");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][2].value).toBe("TEST");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[7][3].value).toBe("\"");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/oneline1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("'''>>> print(\"\"\"docstring\"\"\")'''\nasync\n\"\"\">>> print('''docstring''')\"\"\"\nawait\n\"\"\"\\n>>> print('''docstring''')\"\"\"\nawait\n\"\"\"   >>> print('''docstring''')\"\"\"\nawait\n\"\"\" 1  >>> print('''docstring''')\"\"\"\nawait")
+      expect(tokens[0][0].value).toBe("'''");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe(">>> ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","keyword.control.flow.python"]);
+      expect(tokens[0][2].value).toBe("print(\"\"\"docstring\"\"\")");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[0][3].value).toBe("'''");
+      expect(tokens[0][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("async");
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][0].value).toBe("\"\"\"");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][1].value).toBe(">>> ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","keyword.control.flow.python"]);
+      expect(tokens[2][2].value).toBe("print('''docstring''')");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[2][3].value).toBe("\"\"\"");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("await");
+      expect(tokens[3][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][0].value).toBe("\"\"\"");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][1].value).toBe("\\n");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","constant.character.escape.python"]);
+      expect(tokens[4][2].value).toBe(">>> print('''docstring''')");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[4][3].value).toBe("\"\"\"");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("await");
+      expect(tokens[5][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[6][0].value).toBe("\"\"\"");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][1].value).toBe("   ");
+      expect(tokens[6][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[6][2].value).toBe(">>> ");
+      expect(tokens[6][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","keyword.control.flow.python"]);
+      expect(tokens[6][3].value).toBe("print('''docstring''')");
+      expect(tokens[6][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[6][4].value).toBe("\"\"\"");
+      expect(tokens[6][4].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[7][0].value).toBe("await");
+      expect(tokens[7][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[8][0].value).toBe("\"\"\"");
+      expect(tokens[8][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[8][1].value).toBe(" 1  >>> print('''docstring''')");
+      expect(tokens[8][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[8][2].value).toBe("\"\"\"");
+      expect(tokens[8][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[9][0].value).toBe("await");
+      expect(tokens[9][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/docstrings/oneline2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def foo():\n    '''>>> print(\"\"\"docstring\"\"\")'''\ndef foo():\n    \"\"\">>> print('''docstring''')\"\"\"")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("'''");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe(">>> ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","keyword.control.flow.python"]);
+      expect(tokens[1][3].value).toBe("print(\"\"\"docstring\"\"\")");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[1][4].value).toBe("'''");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("def");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][2].value).toBe("foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[2][4].value).toBe(")");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[2][5].value).toBe(":");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("\"\"\"");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe(">>> ");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","keyword.control.flow.python"]);
+      expect(tokens[3][3].value).toBe("print('''docstring''')");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][4].value).toBe("\"\"\"");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/oneline3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def foo():\n    '>>> print(\"docstring\")'\ndef foo():\n    \">>> print('docstring')\"")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("'");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe(">>> print(\"docstring\")");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[1][3].value).toBe("'");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("def");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][2].value).toBe("foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[2][4].value).toBe(")");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[2][5].value).toBe(":");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("\"");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe(">>> print('docstring')");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[3][3].value).toBe("\"");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/prompt1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("r'''Module docstring\n\n    Some text followed by code sample:\n    >>> for a in foo(2, b=1,\n    ...                 c=3):\n    ...   print(a)\n    0\n    1\n'''")
+      expect(tokens[0][0].value).toBe("r");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[0][1].value).toBe("'''");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("Module docstring");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[2][0].value).toBe("    Some text followed by code sample:");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[3][1].value).toBe(">>> ");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","keyword.control.flow.python"]);
+      expect(tokens[3][2].value).toBe("for a in foo(2, b=1,");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[4][1].value).toBe("... ");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","keyword.control.flow.python"]);
+      expect(tokens[4][2].value).toBe("                c=3):");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[5][1].value).toBe("... ");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","keyword.control.flow.python"]);
+      expect(tokens[5][2].value).toBe("  print(a)");
+      expect(tokens[5][2].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[6][0].value).toBe("    0");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[7][0].value).toBe("    1");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python"]);
+      expect(tokens[8][0].value).toBe("'''");
+      expect(tokens[8][0].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/prompt2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("\"\"\"\n    def foo():\n        ...\n        >>>\n\"\"\"")
+      expect(tokens[0][0].value).toBe("\"\"\"");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][0].value).toBe("    def foo():");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[2][0].value).toBe("        ...");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][0].value).toBe("        >>>");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[4][0].value).toBe("\"\"\"");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/docstrings/prompt3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("'''...'''\n...")
+      expect(tokens[0][0].value).toBe("'''");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe("...");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[0][2].value).toBe("'''");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("...");
+      expect(tokens[1][0].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+    });
+
+  it("test/docstrings/regr1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("#:\n    @asd\n    def foo():\n        pass")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(":");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[1][1].value).toBe("@");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][2].value).toBe("asd");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][1].value).toBe("def");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][3].value).toBe("foo");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[2][4].value).toBe("(");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[2][5].value).toBe(")");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[2][6].value).toBe(":");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[3][0].value).toBe("        ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("pass");
+      expect(tokens[3][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/expressions/const1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("QQQQ QQQQ_123 QQQQ123 PROTOCOL_v2 QQQ.bar baz.AA_a _AAA foo._AAA\nQQQq QQQq123 self.FOOO() _ _1 __1 _1A  __1A _a __a __ ___ ___a ___1 __aA ___Aa")
+      expect(tokens[0][0].value).toBe("QQQQ");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("QQQQ_123");
+      expect(tokens[0][2].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("QQQQ123");
+      expect(tokens[0][4].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("PROTOCOL_v2");
+      expect(tokens[0][6].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("QQQ");
+      expect(tokens[0][8].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][9].value).toBe(".");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("bar");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe(" ");
+      expect(tokens[0][11].scopes).toEqual(["source.python"]);
+      expect(tokens[0][12].value).toBe("baz");
+      expect(tokens[0][12].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].value).toBe(".");
+      expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[0][14].value).toBe("AA_a");
+      expect(tokens[0][14].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][15].value).toBe(" ");
+      expect(tokens[0][15].scopes).toEqual(["source.python"]);
+      expect(tokens[0][16].value).toBe("_AAA");
+      expect(tokens[0][16].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][17].value).toBe(" ");
+      expect(tokens[0][17].scopes).toEqual(["source.python"]);
+      expect(tokens[0][18].value).toBe("foo");
+      expect(tokens[0][18].scopes).toEqual(["source.python"]);
+      expect(tokens[0][19].value).toBe(".");
+      expect(tokens[0][19].scopes).toEqual(["source.python"]);
+      expect(tokens[0][20].value).toBe("_AAA");
+      expect(tokens[0][20].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[1][0].value).toBe("QQQq");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("QQQq123");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("self");
+      expect(tokens[1][4].scopes).toEqual(["source.python","variable.language.special.self.python"]);
+      expect(tokens[1][5].value).toBe(".");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("FOOO");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][7].value).toBe("(");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][8].value).toBe(")");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][9].value).toBe(" ");
+      expect(tokens[1][9].scopes).toEqual(["source.python"]);
+      expect(tokens[1][10].value).toBe("_");
+      expect(tokens[1][10].scopes).toEqual(["source.python"]);
+      expect(tokens[1][11].value).toBe(" ");
+      expect(tokens[1][11].scopes).toEqual(["source.python"]);
+      expect(tokens[1][12].value).toBe("_1");
+      expect(tokens[1][12].scopes).toEqual(["source.python"]);
+      expect(tokens[1][13].value).toBe(" ");
+      expect(tokens[1][13].scopes).toEqual(["source.python"]);
+      expect(tokens[1][14].value).toBe("__1");
+      expect(tokens[1][14].scopes).toEqual(["source.python"]);
+      expect(tokens[1][15].value).toBe(" ");
+      expect(tokens[1][15].scopes).toEqual(["source.python"]);
+      expect(tokens[1][16].value).toBe("_1A");
+      expect(tokens[1][16].scopes).toEqual(["source.python"]);
+      expect(tokens[1][17].value).toBe("  ");
+      expect(tokens[1][17].scopes).toEqual(["source.python"]);
+      expect(tokens[1][18].value).toBe("__1A");
+      expect(tokens[1][18].scopes).toEqual(["source.python"]);
+      expect(tokens[1][19].value).toBe(" ");
+      expect(tokens[1][19].scopes).toEqual(["source.python"]);
+      expect(tokens[1][20].value).toBe("_a");
+      expect(tokens[1][20].scopes).toEqual(["source.python"]);
+      expect(tokens[1][21].value).toBe(" ");
+      expect(tokens[1][21].scopes).toEqual(["source.python"]);
+      expect(tokens[1][22].value).toBe("__a");
+      expect(tokens[1][22].scopes).toEqual(["source.python"]);
+      expect(tokens[1][23].value).toBe(" ");
+      expect(tokens[1][23].scopes).toEqual(["source.python"]);
+      expect(tokens[1][24].value).toBe("__");
+      expect(tokens[1][24].scopes).toEqual(["source.python"]);
+      expect(tokens[1][25].value).toBe(" ");
+      expect(tokens[1][25].scopes).toEqual(["source.python"]);
+      expect(tokens[1][26].value).toBe("___");
+      expect(tokens[1][26].scopes).toEqual(["source.python"]);
+      expect(tokens[1][27].value).toBe(" ");
+      expect(tokens[1][27].scopes).toEqual(["source.python"]);
+      expect(tokens[1][28].value).toBe("___a");
+      expect(tokens[1][28].scopes).toEqual(["source.python"]);
+      expect(tokens[1][29].value).toBe(" ");
+      expect(tokens[1][29].scopes).toEqual(["source.python"]);
+      expect(tokens[1][30].value).toBe("___1");
+      expect(tokens[1][30].scopes).toEqual(["source.python"]);
+      expect(tokens[1][31].value).toBe(" ");
+      expect(tokens[1][31].scopes).toEqual(["source.python"]);
+      expect(tokens[1][32].value).toBe("__aA");
+      expect(tokens[1][32].scopes).toEqual(["source.python"]);
+      expect(tokens[1][33].value).toBe(" ");
+      expect(tokens[1][33].scopes).toEqual(["source.python"]);
+      expect(tokens[1][34].value).toBe("___Aa");
+      expect(tokens[1][34].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/expressions/const2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("_AA __AB ___AA\n_A __A ___A A1 A_1 _A_1 A_foo")
+      expect(tokens[0][0].value).toBe("_AA");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("__AB");
+      expect(tokens[0][2].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("___AA");
+      expect(tokens[0][4].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[1][0].value).toBe("_A");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("__A");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("___A");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("A1");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe(" ");
+      expect(tokens[1][7].scopes).toEqual(["source.python"]);
+      expect(tokens[1][8].value).toBe("A_1");
+      expect(tokens[1][8].scopes).toEqual(["source.python"]);
+      expect(tokens[1][9].value).toBe(" ");
+      expect(tokens[1][9].scopes).toEqual(["source.python"]);
+      expect(tokens[1][10].value).toBe("_A_1");
+      expect(tokens[1][10].scopes).toEqual(["source.python"]);
+      expect(tokens[1][11].value).toBe(" ");
+      expect(tokens[1][11].scopes).toEqual(["source.python"]);
+      expect(tokens[1][12].value).toBe("A_foo");
+      expect(tokens[1][12].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/expressions/expr1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("~a + b @ c ^ d // e % f & e and not g or h")
+      expect(tokens[0][0].value).toBe("~");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.operator.bitwise.python"]);
+      expect(tokens[0][1].value).toBe("a");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe(" ");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe("+");
+      expect(tokens[0][3].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("b");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe("@");
+      expect(tokens[0][7].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe("c");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe("^");
+      expect(tokens[0][11].scopes).toEqual(["source.python","keyword.operator.bitwise.python"]);
+      expect(tokens[0][12].value).toBe(" ");
+      expect(tokens[0][12].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].value).toBe("d");
+      expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[0][14].value).toBe(" ");
+      expect(tokens[0][14].scopes).toEqual(["source.python"]);
+      expect(tokens[0][15].value).toBe("//");
+      expect(tokens[0][15].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][16].value).toBe(" ");
+      expect(tokens[0][16].scopes).toEqual(["source.python"]);
+      expect(tokens[0][17].value).toBe("e");
+      expect(tokens[0][17].scopes).toEqual(["source.python"]);
+      expect(tokens[0][18].value).toBe(" ");
+      expect(tokens[0][18].scopes).toEqual(["source.python"]);
+      expect(tokens[0][19].value).toBe("%");
+      expect(tokens[0][19].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][20].value).toBe(" ");
+      expect(tokens[0][20].scopes).toEqual(["source.python"]);
+      expect(tokens[0][21].value).toBe("f");
+      expect(tokens[0][21].scopes).toEqual(["source.python"]);
+      expect(tokens[0][22].value).toBe(" ");
+      expect(tokens[0][22].scopes).toEqual(["source.python"]);
+      expect(tokens[0][23].value).toBe("&");
+      expect(tokens[0][23].scopes).toEqual(["source.python","keyword.operator.bitwise.python"]);
+      expect(tokens[0][24].value).toBe(" ");
+      expect(tokens[0][24].scopes).toEqual(["source.python"]);
+      expect(tokens[0][25].value).toBe("e");
+      expect(tokens[0][25].scopes).toEqual(["source.python"]);
+      expect(tokens[0][26].value).toBe(" ");
+      expect(tokens[0][26].scopes).toEqual(["source.python"]);
+      expect(tokens[0][27].value).toBe("and");
+      expect(tokens[0][27].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[0][28].value).toBe(" ");
+      expect(tokens[0][28].scopes).toEqual(["source.python"]);
+      expect(tokens[0][29].value).toBe("not");
+      expect(tokens[0][29].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[0][30].value).toBe(" ");
+      expect(tokens[0][30].scopes).toEqual(["source.python"]);
+      expect(tokens[0][31].value).toBe("g");
+      expect(tokens[0][31].scopes).toEqual(["source.python"]);
+      expect(tokens[0][32].value).toBe(" ");
+      expect(tokens[0][32].scopes).toEqual(["source.python"]);
+      expect(tokens[0][33].value).toBe("or");
+      expect(tokens[0][33].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[0][34].value).toBe(" ");
+      expect(tokens[0][34].scopes).toEqual(["source.python"]);
+      expect(tokens[0][35].value).toBe("h");
+      expect(tokens[0][35].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/expressions/expr10.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = ...\na(..., c=...)\na = ((...), ...)\n....__class__")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("...");
+      expect(tokens[0][4].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][1].value).toBe("(");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][2].value).toBe("...");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.other.ellipsis.python"]);
+      expect(tokens[1][3].value).toBe(",");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[1][4].value).toBe(" ");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][5].value).toBe("c");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[1][6].value).toBe("=");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][7].value).toBe("...");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.other.ellipsis.python"]);
+      expect(tokens[1][8].value).toBe(")");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("(");
+      expect(tokens[2][4].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[2][5].value).toBe("(");
+      expect(tokens[2][5].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[2][6].value).toBe("...");
+      expect(tokens[2][6].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[2][7].value).toBe(")");
+      expect(tokens[2][7].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[2][8].value).toBe(",");
+      expect(tokens[2][8].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[2][9].value).toBe(" ");
+      expect(tokens[2][9].scopes).toEqual(["source.python"]);
+      expect(tokens[2][10].value).toBe("...");
+      expect(tokens[2][10].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[2][11].value).toBe(")");
+      expect(tokens[2][11].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[3][0].value).toBe("...");
+      expect(tokens[3][0].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[3][1].value).toBe(".");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("__class__");
+      expect(tokens[3][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+    });
+
+  it("test/expressions/expr11.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = self.some_list[1:2]")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("self");
+      expect(tokens[0][4].scopes).toEqual(["source.python","variable.language.special.self.python"]);
+      expect(tokens[0][5].value).toBe(".");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("some_list");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.item-access.python"]);
+      expect(tokens[0][7].value).toBe("[");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][8].value).toBe("1");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][9].value).toBe(":");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","punctuation.separator.slice.python"]);
+      expect(tokens[0][10].value).toBe("2");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][11].value).toBe("]");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/expressions/expr12.py", 
+    function() {
+      tokens = grammar.tokenizeLines("print []\nprint {}\nprint 1")
+      expect(tokens[0][0].value).toBe("print");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.item-access.python","support.function.builtin.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.item-access.python"]);
+      expect(tokens[0][2].value).toBe("[");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][3].value).toBe("]");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][0].value).toBe("print");
+      expect(tokens[1][0].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("{");
+      expect(tokens[1][2].scopes).toEqual(["source.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[1][3].value).toBe("}");
+      expect(tokens[1][3].scopes).toEqual(["source.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[2][0].value).toBe("print");
+      expect(tokens[2][0].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("1");
+      expect(tokens[2][2].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/expressions/expr13.py", 
+    function() {
+      tokens = grammar.tokenizeLines("super()")
+      expect(tokens[0][0].value).toBe("super");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function-call.python","support.type.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][2].value).toBe(")");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/expressions/expr14.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a <> b")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("<");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
+      expect(tokens[0][3].value).toBe(">");
+      expect(tokens[0][3].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("b");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/expressions/expr15.py", 
+    function() {
+      tokens = grammar.tokenizeLines("foofrom.something")
+      expect(tokens[0][0].value).toBe("foofrom");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("something");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/expressions/expr16.py", 
+    function() {
+      tokens = grammar.tokenizeLines("foo(djsgfjs==123)")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][2].value).toBe("djsgfjs");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][3].value).toBe("==");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.comparison.python"]);
+      expect(tokens[0][4].value).toBe("123");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][5].value).toBe(")");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/expressions/expr17.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a++\nb--\n++a\n--b\na++c\nc--b\na(--a)")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe("++");
+      expect(tokens[0][1].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[1][0].value).toBe("b");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("--");
+      expect(tokens[1][1].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[2][0].value).toBe("++");
+      expect(tokens[2][0].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[2][1].value).toBe("a");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("--");
+      expect(tokens[3][0].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[3][1].value).toBe("b");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("a");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("++");
+      expect(tokens[4][1].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[4][2].value).toBe("c");
+      expect(tokens[4][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("c");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("--");
+      expect(tokens[5][1].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[5][2].value).toBe("b");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("a");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[6][1].value).toBe("(");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[6][2].value).toBe("--");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","invalid.illegal.operator.python"]);
+      expect(tokens[6][3].value).toBe("a");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[6][4].value).toBe(")");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/expressions/expr18.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a.Exception\nException.a")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("Exception");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("Exception");
+      expect(tokens[1][0].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[1][1].value).toBe(".");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("a");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/expressions/expr19.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a. #foo\na.\n#foo\na. \\\n#foo\na. 'bar'\na.\n'bar'\na. \\\n'bar'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(". ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("#");
+      expect(tokens[0][2].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][3].value).toBe("foo");
+      expect(tokens[0][3].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(".");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("#");
+      expect(tokens[2][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][1].value).toBe("foo");
+      expect(tokens[2][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(". ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("\\");
+      expect(tokens[3][2].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[3][3].value).toBe("");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("#");
+      expect(tokens[4][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[4][1].value).toBe("foo");
+      expect(tokens[4][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[5][0].value).toBe("a");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe(". ");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("'");
+      expect(tokens[5][2].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][3].value).toBe("bar");
+      expect(tokens[5][3].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[5][4].value).toBe("'");
+      expect(tokens[5][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][0].value).toBe("a");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe(".");
+      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[7][0].value).toBe("'");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][1].value).toBe("bar");
+      expect(tokens[7][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[7][2].value).toBe("'");
+      expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("a");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe(". ");
+      expect(tokens[8][1].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].value).toBe("\\");
+      expect(tokens[8][2].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[8][3].value).toBe("");
+      expect(tokens[8][3].scopes).toEqual(["source.python"]);
+      expect(tokens[9][0].value).toBe("'");
+      expect(tokens[9][0].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[9][1].value).toBe("bar");
+      expect(tokens[9][1].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[9][2].value).toBe("'");
+      expect(tokens[9][2].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/expressions/expr2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a @= b\na -= c\na ^= d")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("@=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("b");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("-=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("c");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("^=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("d");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/expressions/expr20.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a == b\na != b\na < b\na <= b\na > b\na >= b")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("==");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("b");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("!=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("b");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("<");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("b");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("<=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("b");
+      expect(tokens[3][4].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("a");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe(">");
+      expect(tokens[4][2].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
+      expect(tokens[4][3].value).toBe(" ");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe("b");
+      expect(tokens[4][4].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("a");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe(" ");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe(">=");
+      expect(tokens[5][2].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
+      expect(tokens[5][3].value).toBe(" ");
+      expect(tokens[5][3].scopes).toEqual(["source.python"]);
+      expect(tokens[5][4].value).toBe("b");
+      expect(tokens[5][4].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/expressions/expr3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("(a, *rest, b) = range(5)")
+      expect(tokens[0][0].value).toBe("(");
+      expect(tokens[0][0].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[0][1].value).toBe("a");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe(",");
+      expect(tokens[0][2].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("*");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][5].value).toBe("rest");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe(",");
+      expect(tokens[0][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("b");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe(")");
+      expect(tokens[0][9].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe("=");
+      expect(tokens[0][11].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][12].value).toBe(" ");
+      expect(tokens[0][12].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].value).toBe("range");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[0][14].value).toBe("(");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][15].value).toBe("5");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][16].value).toBe(")");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/expressions/expr4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("arr2 = [i for i in range(7) if i != 3]")
+      expect(tokens[0][0].value).toBe("arr2");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("[");
+      expect(tokens[0][4].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[0][5].value).toBe("i");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe("for");
+      expect(tokens[0][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe("i");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe("in");
+      expect(tokens[0][11].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[0][12].value).toBe(" ");
+      expect(tokens[0][12].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].value).toBe("range");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[0][14].value).toBe("(");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][15].value).toBe("7");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][16].value).toBe(")");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][17].value).toBe(" ");
+      expect(tokens[0][17].scopes).toEqual(["source.python"]);
+      expect(tokens[0][18].value).toBe("if");
+      expect(tokens[0][18].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][19].value).toBe(" ");
+      expect(tokens[0][19].scopes).toEqual(["source.python"]);
+      expect(tokens[0][20].value).toBe("i");
+      expect(tokens[0][20].scopes).toEqual(["source.python"]);
+      expect(tokens[0][21].value).toBe(" ");
+      expect(tokens[0][21].scopes).toEqual(["source.python"]);
+      expect(tokens[0][22].value).toBe("!=");
+      expect(tokens[0][22].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
+      expect(tokens[0][23].value).toBe(" ");
+      expect(tokens[0][23].scopes).toEqual(["source.python"]);
+      expect(tokens[0][24].value).toBe("3");
+      expect(tokens[0][24].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][25].value).toBe("]");
+      expect(tokens[0][25].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+    });
+
+  it("test/expressions/expr5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = (from, a)\nb = [from, b]\nc = {from: {import: a}}")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("(");
+      expect(tokens[0][4].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[0][5].value).toBe("from");
+      expect(tokens[0][5].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][6].value).toBe(",");
+      expect(tokens[0][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("a");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe(")");
+      expect(tokens[0][9].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[1][0].value).toBe("b");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("[");
+      expect(tokens[1][4].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[1][5].value).toBe("from");
+      expect(tokens[1][5].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][6].value).toBe(",");
+      expect(tokens[1][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[1][7].value).toBe(" ");
+      expect(tokens[1][7].scopes).toEqual(["source.python"]);
+      expect(tokens[1][8].value).toBe("b");
+      expect(tokens[1][8].scopes).toEqual(["source.python"]);
+      expect(tokens[1][9].value).toBe("]");
+      expect(tokens[1][9].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[2][0].value).toBe("c");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("{");
+      expect(tokens[2][4].scopes).toEqual(["source.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[2][5].value).toBe("from");
+      expect(tokens[2][5].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][6].value).toBe(":");
+      expect(tokens[2][6].scopes).toEqual(["source.python","punctuation.separator.dict.python"]);
+      expect(tokens[2][7].value).toBe(" ");
+      expect(tokens[2][7].scopes).toEqual(["source.python"]);
+      expect(tokens[2][8].value).toBe("{");
+      expect(tokens[2][8].scopes).toEqual(["source.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[2][9].value).toBe("import");
+      expect(tokens[2][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][10].value).toBe(":");
+      expect(tokens[2][10].scopes).toEqual(["source.python","punctuation.separator.dict.python"]);
+      expect(tokens[2][11].value).toBe(" ");
+      expect(tokens[2][11].scopes).toEqual(["source.python"]);
+      expect(tokens[2][12].value).toBe("a");
+      expect(tokens[2][12].scopes).toEqual(["source.python"]);
+      expect(tokens[2][13].value).toBe("}");
+      expect(tokens[2][13].scopes).toEqual(["source.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[2][14].value).toBe("}");
+      expect(tokens[2][14].scopes).toEqual(["source.python","punctuation.definition.dict.end.python"]);
+    });
+
+  it("test/expressions/expr6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = (a, b(a=1), {c: d(b=1), e: [a, b(z=1)]})")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("(");
+      expect(tokens[0][4].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[0][5].value).toBe("a");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe(",");
+      expect(tokens[0][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("b");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][9].value).toBe("(");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][10].value).toBe("a");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][11].value).toBe("=");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][12].value).toBe("1");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][13].value).toBe(")");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][14].value).toBe(",");
+      expect(tokens[0][14].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][15].value).toBe(" ");
+      expect(tokens[0][15].scopes).toEqual(["source.python"]);
+      expect(tokens[0][16].value).toBe("{");
+      expect(tokens[0][16].scopes).toEqual(["source.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[0][17].value).toBe("c");
+      expect(tokens[0][17].scopes).toEqual(["source.python"]);
+      expect(tokens[0][18].value).toBe(":");
+      expect(tokens[0][18].scopes).toEqual(["source.python","punctuation.separator.dict.python"]);
+      expect(tokens[0][19].value).toBe(" ");
+      expect(tokens[0][19].scopes).toEqual(["source.python"]);
+      expect(tokens[0][20].value).toBe("d");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][21].value).toBe("(");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][22].value).toBe("b");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][23].value).toBe("=");
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][24].value).toBe("1");
+      expect(tokens[0][24].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][25].value).toBe(")");
+      expect(tokens[0][25].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][26].value).toBe(",");
+      expect(tokens[0][26].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][27].value).toBe(" ");
+      expect(tokens[0][27].scopes).toEqual(["source.python"]);
+      expect(tokens[0][28].value).toBe("e");
+      expect(tokens[0][28].scopes).toEqual(["source.python"]);
+      expect(tokens[0][29].value).toBe(":");
+      expect(tokens[0][29].scopes).toEqual(["source.python","punctuation.separator.dict.python"]);
+      expect(tokens[0][30].value).toBe(" ");
+      expect(tokens[0][30].scopes).toEqual(["source.python"]);
+      expect(tokens[0][31].value).toBe("[");
+      expect(tokens[0][31].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[0][32].value).toBe("a");
+      expect(tokens[0][32].scopes).toEqual(["source.python"]);
+      expect(tokens[0][33].value).toBe(",");
+      expect(tokens[0][33].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][34].value).toBe(" ");
+      expect(tokens[0][34].scopes).toEqual(["source.python"]);
+      expect(tokens[0][35].value).toBe("b");
+      expect(tokens[0][35].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][36].value).toBe("(");
+      expect(tokens[0][36].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][37].value).toBe("z");
+      expect(tokens[0][37].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][38].value).toBe("=");
+      expect(tokens[0][38].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][39].value).toBe("1");
+      expect(tokens[0][39].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][40].value).toBe(")");
+      expect(tokens[0][40].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][41].value).toBe("]");
+      expect(tokens[0][41].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[0][42].value).toBe("}");
+      expect(tokens[0][42].scopes).toEqual(["source.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[0][43].value).toBe(")");
+      expect(tokens[0][43].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+    });
+
+  it("test/expressions/expr7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a.True = b.False = d.None")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("True");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("=");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("b");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe(".");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("False");
+      expect(tokens[0][8].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("=");
+      expect(tokens[0][10].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][11].value).toBe(" ");
+      expect(tokens[0][11].scopes).toEqual(["source.python"]);
+      expect(tokens[0][12].value).toBe("d");
+      expect(tokens[0][12].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].value).toBe(".");
+      expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[0][14].value).toBe("None");
+      expect(tokens[0][14].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+    });
+
+  it("test/expressions/expr8.py", 
+    function() {
+      tokens = grammar.tokenizeLines("assert a or b, 'aaa'")
+      expect(tokens[0][0].value).toBe("assert");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("a");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("or");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("b");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe(",");
+      expect(tokens[0][7].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe("'");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][10].value).toBe("aaa");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][11].value).toBe("'");
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/expressions/expr9.py", 
+    function() {
+      tokens = grammar.tokenizeLines("yield  from a\nyield a")
+      expect(tokens[0][0].value).toBe("yield  from");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("a");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("yield");
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("a");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/expressions/keywords.py", 
+    function() {
+      tokens = grammar.tokenizeLines("as async await continue del assert break finally for\nfrom elif else if import except pass raise\nreturn try while with\n\nnonlocal global class def")
+      expect(tokens[0][0].value).toBe("as");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("async");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("await");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("continue");
+      expect(tokens[0][6].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("del");
+      expect(tokens[0][8].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("assert");
+      expect(tokens[0][10].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][11].value).toBe(" ");
+      expect(tokens[0][11].scopes).toEqual(["source.python"]);
+      expect(tokens[0][12].value).toBe("break");
+      expect(tokens[0][12].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][13].value).toBe(" ");
+      expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[0][14].value).toBe("finally");
+      expect(tokens[0][14].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][15].value).toBe(" ");
+      expect(tokens[0][15].scopes).toEqual(["source.python"]);
+      expect(tokens[0][16].value).toBe("for");
+      expect(tokens[0][16].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][0].value).toBe("from");
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("elif");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("else");
+      expect(tokens[1][4].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("if");
+      expect(tokens[1][6].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][7].value).toBe(" ");
+      expect(tokens[1][7].scopes).toEqual(["source.python"]);
+      expect(tokens[1][8].value).toBe("import");
+      expect(tokens[1][8].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][9].value).toBe(" ");
+      expect(tokens[1][9].scopes).toEqual(["source.python"]);
+      expect(tokens[1][10].value).toBe("except");
+      expect(tokens[1][10].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][11].value).toBe(" ");
+      expect(tokens[1][11].scopes).toEqual(["source.python"]);
+      expect(tokens[1][12].value).toBe("pass");
+      expect(tokens[1][12].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][13].value).toBe(" ");
+      expect(tokens[1][13].scopes).toEqual(["source.python"]);
+      expect(tokens[1][14].value).toBe("raise");
+      expect(tokens[1][14].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][0].value).toBe("return");
+      expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("try");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("while");
+      expect(tokens[2][4].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("with");
+      expect(tokens[2][6].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[3][0].value).toBe("");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("nonlocal");
+      expect(tokens[4][0].scopes).toEqual(["source.python","storage.modifier.declaration.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("global");
+      expect(tokens[4][2].scopes).toEqual(["source.python","storage.modifier.declaration.python"]);
+      expect(tokens[4][3].value).toBe(" ");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe("class");
+      expect(tokens[4][4].scopes).toEqual(["source.python","storage.type.class.python"]);
+      expect(tokens[4][5].value).toBe(" def");
+      expect(tokens[4][5].scopes).toEqual(["source.python","storage.type.function.python"]);
+    });
+
+  it("test/expressions/special1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("__version__ __doc__ __file__\n__author__")
+      expect(tokens[0][0].value).toBe("__version__");
+      expect(tokens[0][0].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("__doc__");
+      expect(tokens[0][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("__file__");
+      expect(tokens[0][4].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[1][0].value).toBe("__author__");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/fstrings/comment1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f'prefix{10 # comment, making the string technically illegal\ndef foo(): pass")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("prefix");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][4].value).toBe("10");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][5].value).toBe(" # ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][6].value).toBe("comment");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][7].value).toBe(",");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","punctuation.separator.element.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][9].value).toBe("making");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][11].value).toBe("the");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][12].value).toBe(" ");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][13].value).toBe("string");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][14].value).toBe(" ");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][15].value).toBe("technically");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][16].value).toBe(" ");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][17].value).toBe("illegal");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][18].value).toBe("");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.newline.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("foo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe("pass");
+      expect(tokens[1][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/fstrings/comment2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f'''\n    prefix{10\n    + 32} suffix'''")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'''");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][0].value).toBe("    prefix");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][1].value).toBe("{");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][2].value).toBe("10");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][1].value).toBe("+");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][3].value).toBe("32");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[2][4].value).toBe("}");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][5].value).toBe(" suffix");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][6].value).toBe("'''");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/comment3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f'''\n    prefix{10 # comment is still illegal here\n    } suffix'''")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'''");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][0].value).toBe("    prefix");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][1].value).toBe("{");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][2].value).toBe("10");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[1][3].value).toBe(" # ");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][4].value).toBe("comment");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][6].value).toBe("is");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","keyword.operator.logical.python"]);
+      expect(tokens[1][7].value).toBe(" ");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][8].value).toBe("still");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][9].value).toBe(" ");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][10].value).toBe("illegal");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][11].value).toBe(" ");
+      expect(tokens[1][11].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][12].value).toBe("here");
+      expect(tokens[1][12].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][1].value).toBe("}");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][2].value).toBe(" suffix");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][3].value).toBe("'''");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/comment4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("self.assertEqual(f'{10:#{3 != {4:5} and width}x}', '       0xa')")
+      expect(tokens[0][0].value).toBe("self");
+      expect(tokens[0][0].scopes).toEqual(["source.python","variable.language.special.self.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("assertEqual");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][4].value).toBe("f");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("{");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe("10");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][8].value).toBe(":");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][9].value).toBe("#");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][10].value).toBe("{");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][11].value).toBe("3");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][12].value).toBe(" ");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[0][13].value).toBe("!=");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","keyword.operator.comparison.python"]);
+      expect(tokens[0][14].value).toBe(" ");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[0][15].value).toBe("{");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[0][16].value).toBe("4");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][17].value).toBe(":");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","punctuation.separator.dict.python"]);
+      expect(tokens[0][18].value).toBe("5");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][19].value).toBe("}");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[0][20].value).toBe(" ");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[0][21].value).toBe("and");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","keyword.operator.logical.python"]);
+      expect(tokens[0][22].value).toBe(" ");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[0][23].value).toBe("width");
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[0][24].value).toBe("}");
+      expect(tokens[0][24].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][25].value).toBe("x");
+      expect(tokens[0][25].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][26].value).toBe("}");
+      expect(tokens[0][26].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][27].value).toBe("'");
+      expect(tokens[0][27].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[0][28].value).toBe(",");
+      expect(tokens[0][28].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[0][29].value).toBe(" ");
+      expect(tokens[0][29].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][30].value).toBe("'");
+      expect(tokens[0][30].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][31].value).toBe("       0xa");
+      expect(tokens[0][31].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[0][32].value).toBe("'");
+      expect(tokens[0][32].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][33].value).toBe(")");
+      expect(tokens[0][33].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/fstrings/empty1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f\"{} {  }\"\nf\"\"\"{}\n{  }\n\"\"\"")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("\"");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("{");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][3].value).toBe("}");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("{");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].value).toBe("  ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.brace.python"]);
+      expect(tokens[0][7].value).toBe("}");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][8].value).toBe("\"");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("f");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][1].value).toBe("\"\"\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("{");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][3].value).toBe("}");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][4].value).toBe("");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][0].value).toBe("{");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][1].value).toBe("  ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.brace.python"]);
+      expect(tokens[2][2].value).toBe("}");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][3].value).toBe("");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[3][0].value).toBe("\"\"\"");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/empty2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("rf\"{} {  }\"\nrf\"\"\"{}\n{  }\n\"\"\"")
+      expect(tokens[0][0].value).toBe("rf");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[0][1].value).toBe("\"");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("{");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][3].value).toBe("}");
+      expect(tokens[0][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("{");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].value).toBe("  ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","invalid.illegal.brace.python"]);
+      expect(tokens[0][7].value).toBe("}");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][8].value).toBe("\"");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("rf");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[1][1].value).toBe("\"\"\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("{");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][3].value).toBe("}");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][0].value).toBe("{");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][1].value).toBe("  ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","invalid.illegal.brace.python"]);
+      expect(tokens[2][2].value).toBe("}");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][0].value).toBe("\"\"\"");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/nested1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f'''\n    prefix {\n        foo(f\"\"\"\n            inner prefix\n            { bar[\"q\"] + f'insane{42 + 9000}stuff{def aaa(): pass}111'}\n            inner suffix\n        \"\"\")\n    } suffix\n'''")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'''");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][0].value).toBe("    prefix ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][1].value).toBe("{");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][0].value).toBe("        ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][1].value).toBe("foo");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[2][2].value).toBe("(");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][3].value).toBe("f");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][4].value).toBe("\"\"\"");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[2][5].value).toBe("");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[3][0].value).toBe("            inner prefix");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[4][0].value).toBe("            ");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[4][1].value).toBe("{");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[4][2].value).toBe(" ");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[4][3].value).toBe("bar");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.item-access.python"]);
+      expect(tokens[4][4].value).toBe("[");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[4][5].value).toBe("\"");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.item-access.python","meta.item-access.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][6].value).toBe("q");
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.item-access.python","meta.item-access.arguments.python","string.quoted.single.python"]);
+      expect(tokens[4][7].value).toBe("\"");
+      expect(tokens[4][7].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.item-access.python","meta.item-access.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][8].value).toBe("]");
+      expect(tokens[4][8].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[4][9].value).toBe(" ");
+      expect(tokens[4][9].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[4][10].value).toBe("+");
+      expect(tokens[4][10].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[4][11].value).toBe(" ");
+      expect(tokens[4][11].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[4][12].value).toBe("f");
+      expect(tokens[4][12].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[4][13].value).toBe("'");
+      expect(tokens[4][13].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[4][14].value).toBe("insane");
+      expect(tokens[4][14].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[4][15].value).toBe("{");
+      expect(tokens[4][15].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[4][16].value).toBe("42");
+      expect(tokens[4][16].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[4][17].value).toBe(" ");
+      expect(tokens[4][17].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python"]);
+      expect(tokens[4][18].value).toBe("+");
+      expect(tokens[4][18].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[4][19].value).toBe(" ");
+      expect(tokens[4][19].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python"]);
+      expect(tokens[4][20].value).toBe("9000");
+      expect(tokens[4][20].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[4][21].value).toBe("}");
+      expect(tokens[4][21].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[4][22].value).toBe("stuff");
+      expect(tokens[4][22].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[4][23].value).toBe("{");
+      expect(tokens[4][23].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[4][24].value).toBe("def");
+      expect(tokens[4][24].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","keyword.control.flow.python"]);
+      expect(tokens[4][25].value).toBe(" ");
+      expect(tokens[4][25].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python"]);
+      expect(tokens[4][26].value).toBe("aaa");
+      expect(tokens[4][26].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[4][27].value).toBe("(");
+      expect(tokens[4][27].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[4][28].value).toBe(")");
+      expect(tokens[4][28].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[4][29].value).toBe(":");
+      expect(tokens[4][29].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","punctuation.separator.colon.python"]);
+      expect(tokens[4][30].value).toBe(" ");
+      expect(tokens[4][30].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python"]);
+      expect(tokens[4][31].value).toBe("pass");
+      expect(tokens[4][31].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","keyword.control.flow.python"]);
+      expect(tokens[4][32].value).toBe("}");
+      expect(tokens[4][32].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[4][33].value).toBe("111");
+      expect(tokens[4][33].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[4][34].value).toBe("'");
+      expect(tokens[4][34].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[4][35].value).toBe("}");
+      expect(tokens[4][35].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[4][36].value).toBe("");
+      expect(tokens[4][36].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[5][0].value).toBe("            inner suffix");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[6][0].value).toBe("        ");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[6][1].value).toBe("\"\"\"");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[6][2].value).toBe(")");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[7][1].value).toBe("}");
+      expect(tokens[7][1].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[7][2].value).toBe(" suffix");
+      expect(tokens[7][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[8][0].value).toBe("'''");
+      expect(tokens[8][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/nested2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f\"result: {value:{60}.{16!s:2}{'qwerty'[2]}}\"")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("\"");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("result: ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][4].value).toBe("value");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][6].value).toBe("{");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe("60");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][8].value).toBe("}");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][9].value).toBe(".");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][10].value).toBe("{");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][11].value).toBe("16");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][12].value).toBe("!s");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][13].value).toBe(":2");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][14].value).toBe("}");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][15].value).toBe("{");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][16].value).toBe("'");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][17].value).toBe("qwerty");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python"]);
+      expect(tokens[0][18].value).toBe("'");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][19].value).toBe("[");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[0][20].value).toBe("2");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][21].value).toBe("]");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.fstring.python","punctuation.definition.list.end.python"]);
+      expect(tokens[0][22].value).toBe("}");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][23].value).toBe("}");
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][24].value).toBe("\"");
+      expect(tokens[0][24].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/nested3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f\"result: {value:{60}.{16!s:2}{'qwerty'\n[2]}}\"")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("\"");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("result: ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][4].value).toBe("value");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][6].value).toBe("{");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe("60");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][8].value).toBe("}");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][9].value).toBe(".");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][10].value).toBe("{");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][11].value).toBe("16");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][12].value).toBe("!s");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][13].value).toBe(":2");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][14].value).toBe("}");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][15].value).toBe("{");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][16].value).toBe("'");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][17].value).toBe("qwerty");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python"]);
+      expect(tokens[0][18].value).toBe("'");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][19].value).toBe("");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.newline.python"]);
+      expect(tokens[1][0].value).toBe("[");
+      expect(tokens[1][0].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[1][1].value).toBe("2");
+      expect(tokens[1][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][2].value).toBe("]");
+      expect(tokens[1][2].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[1][3].value).toBe("}}");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("\"");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][5].value).toBe("");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python","invalid.illegal.newline.python"]);
+    });
+
+  it("test/fstrings/nested4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f\"\"\"result: {value:{60}.{16!s:2}{'qwerty'\n[2]}}\"\"\"\ndef foo(): pass")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("\"\"\"");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("result: ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][4].value).toBe("value");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][6].value).toBe("{");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe("60");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][8].value).toBe("}");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][9].value).toBe(".");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][10].value).toBe("{");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][11].value).toBe("16");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][12].value).toBe("!s");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][13].value).toBe(":2");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][14].value).toBe("}");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][15].value).toBe("{");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][16].value).toBe("'");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][17].value).toBe("qwerty");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python"]);
+      expect(tokens[0][18].value).toBe("'");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("[");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[1][1].value).toBe("2");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[1][2].value).toBe("]");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","punctuation.definition.list.end.python"]);
+      expect(tokens[1][3].value).toBe("}");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][4].value).toBe("}");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][5].value).toBe("\"\"\"");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("def");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][2].value).toBe("foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[2][4].value).toBe(")");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[2][5].value).toBe(":");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[2][6].value).toBe(" ");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][7].value).toBe("pass");
+      expect(tokens[2][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/fstrings/prefixes1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = f's t r'\na = f\"s t r\"\na = F's t r'\na = F\"s t r\"\na = f'''s t r'''\na = F\"\"\"s t r\"\"\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("f");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("s t r");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("f");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][5].value).toBe("\"");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("s t r");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][7].value).toBe("\"");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("F");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("s t r");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][7].value).toBe("'");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("F");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[3][5].value).toBe("\"");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[3][6].value).toBe("s t r");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[3][7].value).toBe("\"");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("a");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("=");
+      expect(tokens[4][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][3].value).toBe(" ");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe("f");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[4][5].value).toBe("'''");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[4][6].value).toBe("s t r");
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[4][7].value).toBe("'''");
+      expect(tokens[4][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("a");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe(" ");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("=");
+      expect(tokens[5][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[5][3].value).toBe(" ");
+      expect(tokens[5][3].scopes).toEqual(["source.python"]);
+      expect(tokens[5][4].value).toBe("F");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[5][5].value).toBe("\"\"\"");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[5][6].value).toBe("s t r");
+      expect(tokens[5][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[5][7].value).toBe("\"\"\"");
+      expect(tokens[5][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/prefixes2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f'some {obj}'\nF'some {obj}'\nrf'some {obj}'\nrF'some {obj}'\nRf'some {obj}'\nRF'some {obj}'")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("some ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][4].value).toBe("obj");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][5].value).toBe("}");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].value).toBe("'");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("F");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][1].value).toBe("'");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("some ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][3].value).toBe("{");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][4].value).toBe("obj");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][5].value).toBe("}");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][6].value).toBe("'");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("rf");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[2][1].value).toBe("'");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("some ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][3].value).toBe("{obj}");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][4].value).toBe("'");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("rF");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[3][1].value).toBe("'");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe("some ");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[3][3].value).toBe("{obj}");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[3][4].value).toBe("'");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("Rf");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[4][1].value).toBe("'");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[4][2].value).toBe("some ");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[4][3].value).toBe("{");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[4][4].value).toBe("obj");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[4][5].value).toBe("}");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[4][6].value).toBe("'");
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("RF");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[5][1].value).toBe("'");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[5][2].value).toBe("some ");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[5][3].value).toBe("{");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[5][4].value).toBe("obj");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[5][5].value).toBe("}");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[5][6].value).toBe("'");
+      expect(tokens[5][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/prefixes3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("fr'some {obj}'\nFr'some {obj}'\nfR'some {obj}'\nFR'some {obj}'")
+      expect(tokens[0][0].value).toBe("fr");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("some ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{obj}");
+      expect(tokens[0][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("Fr");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[1][1].value).toBe("'");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("some ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][3].value).toBe("{obj}");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][4].value).toBe("'");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("fR");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[2][1].value).toBe("'");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("some ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[2][3].value).toBe("{");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][4].value).toBe("obj");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][5].value).toBe("}");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][6].value).toBe("'");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("FR");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[3][1].value).toBe("'");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe("some ");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[3][3].value).toBe("{");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][4].value).toBe("obj");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[3][5].value).toBe("}");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][6].value).toBe("'");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/prefixes4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("fu'some {obj}'\nFu'some {obj}'\nfU'some {obj}'\nFU'some {obj}'\n\nuf'some {obj}'\nuF'some {obj}'\nUf'some {obj}'\nUF'some {obj}'")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("u");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[0][2].value).toBe("'");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][3].value).toBe("some ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][4].value).toBe("{");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][5].value).toBe("obj");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][6].value).toBe("}");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("F");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][1].value).toBe("u");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[1][2].value).toBe("'");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[1][3].value).toBe("some ");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][4].value).toBe("{");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][5].value).toBe("obj");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][6].value).toBe("}");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][7].value).toBe("'");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("f");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][1].value).toBe("U");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[2][2].value).toBe("'");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[2][3].value).toBe("some ");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][4].value).toBe("{");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][5].value).toBe("obj");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][6].value).toBe("}");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][7].value).toBe("'");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("F");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[3][1].value).toBe("U");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[3][2].value).toBe("'");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[3][3].value).toBe("some ");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[3][4].value).toBe("{");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][5].value).toBe("obj");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[3][6].value).toBe("}");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][7].value).toBe("'");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("u");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[5][1].value).toBe("f");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[5][2].value).toBe("'");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[5][3].value).toBe("some ");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[5][4].value).toBe("{");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[5][5].value).toBe("obj");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[5][6].value).toBe("}");
+      expect(tokens[5][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[5][7].value).toBe("'");
+      expect(tokens[5][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[6][0].value).toBe("u");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[6][1].value).toBe("F");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[6][2].value).toBe("'");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[6][3].value).toBe("some ");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[6][4].value).toBe("{");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[6][5].value).toBe("obj");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[6][6].value).toBe("}");
+      expect(tokens[6][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[6][7].value).toBe("'");
+      expect(tokens[6][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[7][0].value).toBe("U");
+      expect(tokens[7][0].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[7][1].value).toBe("f");
+      expect(tokens[7][1].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[7][2].value).toBe("'");
+      expect(tokens[7][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[7][3].value).toBe("some ");
+      expect(tokens[7][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[7][4].value).toBe("{");
+      expect(tokens[7][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[7][5].value).toBe("obj");
+      expect(tokens[7][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[7][6].value).toBe("}");
+      expect(tokens[7][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[7][7].value).toBe("'");
+      expect(tokens[7][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("U");
+      expect(tokens[8][0].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[8][1].value).toBe("F");
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[8][2].value).toBe("'");
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[8][3].value).toBe("some ");
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[8][4].value).toBe("{");
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[8][5].value).toBe("obj");
+      expect(tokens[8][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[8][6].value).toBe("}");
+      expect(tokens[8][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[8][7].value).toBe("'");
+      expect(tokens[8][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/prefixes5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("fb'some {obj}'\nFb'some {obj}'\nfB'some {obj}'\nFB'some {obj}'\n\nbf'some {obj}'\nbF'some {obj}'\nBf'some {obj}'\nBF'some {obj}'")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("b");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[0][2].value).toBe("'");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][3].value).toBe("some ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][4].value).toBe("{");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][5].value).toBe("obj");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][6].value).toBe("}");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("F");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][1].value).toBe("b");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[1][2].value).toBe("'");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[1][3].value).toBe("some ");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][4].value).toBe("{");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][5].value).toBe("obj");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][6].value).toBe("}");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][7].value).toBe("'");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("f");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][1].value).toBe("B");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[2][2].value).toBe("'");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[2][3].value).toBe("some ");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][4].value).toBe("{");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][5].value).toBe("obj");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][6].value).toBe("}");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][7].value).toBe("'");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("F");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[3][1].value).toBe("B");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[3][2].value).toBe("'");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[3][3].value).toBe("some ");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[3][4].value).toBe("{");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][5].value).toBe("obj");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[3][6].value).toBe("}");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][7].value).toBe("'");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("b");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[5][1].value).toBe("f");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[5][2].value).toBe("'");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[5][3].value).toBe("some ");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[5][4].value).toBe("{");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[5][5].value).toBe("obj");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[5][6].value).toBe("}");
+      expect(tokens[5][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[5][7].value).toBe("'");
+      expect(tokens[5][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[6][0].value).toBe("b");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[6][1].value).toBe("F");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[6][2].value).toBe("'");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[6][3].value).toBe("some ");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[6][4].value).toBe("{");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[6][5].value).toBe("obj");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[6][6].value).toBe("}");
+      expect(tokens[6][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[6][7].value).toBe("'");
+      expect(tokens[6][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[7][0].value).toBe("B");
+      expect(tokens[7][0].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[7][1].value).toBe("f");
+      expect(tokens[7][1].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[7][2].value).toBe("'");
+      expect(tokens[7][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[7][3].value).toBe("some ");
+      expect(tokens[7][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[7][4].value).toBe("{");
+      expect(tokens[7][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[7][5].value).toBe("obj");
+      expect(tokens[7][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[7][6].value).toBe("}");
+      expect(tokens[7][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[7][7].value).toBe("'");
+      expect(tokens[7][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("B");
+      expect(tokens[8][0].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.prefix.python"]);
+      expect(tokens[8][1].value).toBe("F");
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[8][2].value).toBe("'");
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[8][3].value).toBe("some ");
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[8][4].value).toBe("{");
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[8][5].value).toBe("obj");
+      expect(tokens[8][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[8][6].value).toBe("}");
+      expect(tokens[8][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[8][7].value).toBe("'");
+      expect(tokens[8][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/simple1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = f\"{0[ ]:X>+10d}\"\na = f\"{0[ ]!s:X>+10d}\"\na = f\"{0[ ]:Xd>+10d}\" #invalid")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("f");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("\"");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("{");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe("0");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][8].value).toBe("[");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][10].value).toBe("]");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","punctuation.definition.list.end.python"]);
+      expect(tokens[0][11].value).toBe(":X>+10d");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][12].value).toBe("}");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][13].value).toBe("\"");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("f");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][5].value).toBe("\"");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("{");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][7].value).toBe("0");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[1][8].value).toBe("[");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.fstring.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[1][9].value).toBe(" ");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][10].value).toBe("]");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.fstring.python","punctuation.definition.list.end.python"]);
+      expect(tokens[1][11].value).toBe("!s");
+      expect(tokens[1][11].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[1][12].value).toBe(":X>+10d");
+      expect(tokens[1][12].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[1][13].value).toBe("}");
+      expect(tokens[1][13].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][14].value).toBe("\"");
+      expect(tokens[1][14].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("f");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][5].value).toBe("\"");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("{");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][7].value).toBe("0");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[2][8].value).toBe("[");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.fstring.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[2][9].value).toBe(" ");
+      expect(tokens[2][9].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][10].value).toBe("]");
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.fstring.python","punctuation.definition.list.end.python"]);
+      expect(tokens[2][11].value).toBe(":");
+      expect(tokens[2][11].scopes).toEqual(["source.python","meta.fstring.python","punctuation.separator.colon.python"]);
+      expect(tokens[2][12].value).toBe("Xd");
+      expect(tokens[2][12].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][13].value).toBe(">");
+      expect(tokens[2][13].scopes).toEqual(["source.python","meta.fstring.python","keyword.operator.comparison.python"]);
+      expect(tokens[2][14].value).toBe("+");
+      expect(tokens[2][14].scopes).toEqual(["source.python","meta.fstring.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[2][15].value).toBe("10d");
+      expect(tokens[2][15].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.name.python"]);
+      expect(tokens[2][16].value).toBe("}");
+      expect(tokens[2][16].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][17].value).toBe("\"");
+      expect(tokens[2][17].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][18].value).toBe(" ");
+      expect(tokens[2][18].scopes).toEqual(["source.python"]);
+      expect(tokens[2][19].value).toBe("#");
+      expect(tokens[2][19].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][20].value).toBe("invalid");
+      expect(tokens[2][20].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/fstrings/simple2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = f\"normal {{ normal }} normal } {10!r} normal {fo.__add__!s}\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("f");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("\"");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("normal ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][7].value).toBe("{{");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][8].value).toBe(" normal ");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][9].value).toBe("}}");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][10].value).toBe(" normal ");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][11].value).toBe("}");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.brace.python"]);
+      expect(tokens[0][12].value).toBe(" ");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][13].value).toBe("{");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][14].value).toBe("10");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][15].value).toBe("!r");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][16].value).toBe("}");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][17].value).toBe(" normal ");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][18].value).toBe("{");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][19].value).toBe("fo");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][20].value).toBe(".");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][21].value).toBe("__add__");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.fstring.python","support.function.magic.python"]);
+      expect(tokens[0][22].value).toBe("!s");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][23].value).toBe("}");
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][24].value).toBe("\"");
+      expect(tokens[0][24].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/simple3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = f'hello { foo(\"bar\")/23 !r:f} times'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("f");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("hello ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][7].value).toBe("{");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][9].value).toBe("foo");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][10].value).toBe("(");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][11].value).toBe("\"");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][12].value).toBe("bar");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[0][13].value).toBe("\"");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][14].value).toBe(")");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][15].value).toBe("/");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.fstring.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][16].value).toBe("23");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][17].value).toBe(" ");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][18].value).toBe("!r");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][19].value).toBe(":f");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][20].value).toBe("}");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][21].value).toBe(" times");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][22].value).toBe("'");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/simple4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = f'''hello { foo(\"bar\")/23 !r:f} times'''")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("f");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("'''");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("hello ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[0][7].value).toBe("{");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][9].value).toBe("foo");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][10].value).toBe("(");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][11].value).toBe("\"");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][12].value).toBe("bar");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[0][13].value).toBe("\"");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][14].value).toBe(")");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][15].value).toBe("/");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.fstring.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][16].value).toBe("23");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][17].value).toBe(" ");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][18].value).toBe("!r");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][19].value).toBe(":f");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][20].value).toBe("}");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][21].value).toBe(" times");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[0][22].value).toBe("'''");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/simple5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = f'''\nhello { foo(\"bar\")/23 !r:f} times\n'''")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("f");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("'''");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][0].value).toBe("hello ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][1].value).toBe("{");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][3].value).toBe("foo");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][4].value).toBe("(");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][5].value).toBe("\"");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("bar");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[1][7].value).toBe("\"");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][8].value).toBe(")");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][9].value).toBe("/");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.fstring.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[1][10].value).toBe("23");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[1][11].value).toBe(" ");
+      expect(tokens[1][11].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][12].value).toBe("!r");
+      expect(tokens[1][12].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[1][13].value).toBe(":f");
+      expect(tokens[1][13].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[1][14].value).toBe("}");
+      expect(tokens[1][14].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][15].value).toBe(" times");
+      expect(tokens[1][15].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][0].value).toBe("'''");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/simple6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f'insane{42 + 9000}stuff{def aaa(): pass}'\n# def aaa() must not be parsed as a valid declaration")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("insane");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][4].value).toBe("42");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][6].value).toBe("+");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][8].value).toBe("9000");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][9].value).toBe("}");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][10].value).toBe("stuff");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][11].value).toBe("{");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][12].value).toBe("def");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","keyword.control.flow.python"]);
+      expect(tokens[0][13].value).toBe(" ");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][14].value).toBe("aaa");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][15].value).toBe("(");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][16].value).toBe(")");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][17].value).toBe(":");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.fstring.python","punctuation.separator.colon.python"]);
+      expect(tokens[0][18].value).toBe(" ");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][19].value).toBe("pass");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python","keyword.control.flow.python"]);
+      expect(tokens[0][20].value).toBe("}");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][21].value).toBe("'");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("#");
+      expect(tokens[1][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][1].value).toBe(" def aaa() must not be parsed as a valid declaration");
+      expect(tokens[1][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/fstrings/simple7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f'abc \\ efg'")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("abc ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("\\ efg");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/simple8.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f'abc \\} }} }}} }}}} }}}}} efg'")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("abc ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("\\");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][4].value).toBe("}");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.brace.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][6].value).toBe("}}");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][8].value).toBe("}}");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][9].value).toBe("}");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.brace.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][11].value).toBe("}}");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][12].value).toBe("}}");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][13].value).toBe(" ");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][14].value).toBe("}}");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][15].value).toBe("}}");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][16].value).toBe("}");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.brace.python"]);
+      expect(tokens[0][17].value).toBe(" efg");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][18].value).toBe("'");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/simple9.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f'foo {{{bar}}}'")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("foo ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{{");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][4].value).toBe("{");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][5].value).toBe("bar");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][6].value).toBe("}");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe("}}");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][8].value).toBe("'");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/unicode1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = f\"\"\"\nmultiline \"unicode\" string \\\n\n    \\xf1 \\u1234aaaa \\U1234aaaa\n\n    \\N{BLACK SPADE SUIT}\n\"\"\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("f");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("\"\"\"");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][0].value).toBe("multiline \"unicode\" string ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][1].value).toBe("\\");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","constant.language.python"]);
+      expect(tokens[1][2].value).toBe("");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[3][1].value).toBe("\\xf1");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[3][3].value).toBe("\\u1234");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[3][4].value).toBe("aaaa ");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[3][5].value).toBe("\\U1234aaaa");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[3][6].value).toBe("");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[5][1].value).toBe("\\N{BLACK SPADE SUIT}");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[5][2].value).toBe("");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[6][0].value).toBe("\"\"\"");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/unicode2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = f\"\"\"\nmultiline \"unicode\" string\n    \\N{BLACK SPADE SUIT} {foo+2}\n\"\"\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("f");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("\"\"\"");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[1][0].value).toBe("multiline \"unicode\" string");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][1].value).toBe("\\N{BLACK SPADE SUIT}");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][3].value).toBe("{");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][4].value).toBe("foo");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][5].value).toBe("+");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[2][6].value).toBe("2");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[2][7].value).toBe("}");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][8].value).toBe("");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[3][0].value).toBe("\"\"\"");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/functions/async1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("@foo\nasync def foo():\n    a = 1\n    async for a, b, c in b:\n        async with b as d, c:\n            await func(a, b=1)")
+      expect(tokens[0][0].value).toBe("@");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][1].value).toBe("foo");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][0].value).toBe("async");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.async.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("def");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][4].value).toBe("foo");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][5].value).toBe("(");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][6].value).toBe(")");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][7].value).toBe(":");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("a");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe("=");
+      expect(tokens[2][3].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][4].value).toBe(" ");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][5].value).toBe("1");
+      expect(tokens[2][5].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("async");
+      expect(tokens[3][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("for");
+      expect(tokens[3][3].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[3][4].value).toBe(" ");
+      expect(tokens[3][4].scopes).toEqual(["source.python"]);
+      expect(tokens[3][5].value).toBe("a");
+      expect(tokens[3][5].scopes).toEqual(["source.python"]);
+      expect(tokens[3][6].value).toBe(",");
+      expect(tokens[3][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[3][7].value).toBe(" ");
+      expect(tokens[3][7].scopes).toEqual(["source.python"]);
+      expect(tokens[3][8].value).toBe("b");
+      expect(tokens[3][8].scopes).toEqual(["source.python"]);
+      expect(tokens[3][9].value).toBe(",");
+      expect(tokens[3][9].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[3][10].value).toBe(" ");
+      expect(tokens[3][10].scopes).toEqual(["source.python"]);
+      expect(tokens[3][11].value).toBe("c");
+      expect(tokens[3][11].scopes).toEqual(["source.python"]);
+      expect(tokens[3][12].value).toBe(" ");
+      expect(tokens[3][12].scopes).toEqual(["source.python"]);
+      expect(tokens[3][13].value).toBe("in");
+      expect(tokens[3][13].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[3][14].value).toBe(" ");
+      expect(tokens[3][14].scopes).toEqual(["source.python"]);
+      expect(tokens[3][15].value).toBe("b");
+      expect(tokens[3][15].scopes).toEqual(["source.python"]);
+      expect(tokens[3][16].value).toBe(":");
+      expect(tokens[3][16].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[4][0].value).toBe("        ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("async");
+      expect(tokens[4][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][2].value).toBe(" ");
+      expect(tokens[4][2].scopes).toEqual(["source.python"]);
+      expect(tokens[4][3].value).toBe("with");
+      expect(tokens[4][3].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][4].value).toBe(" ");
+      expect(tokens[4][4].scopes).toEqual(["source.python"]);
+      expect(tokens[4][5].value).toBe("b");
+      expect(tokens[4][5].scopes).toEqual(["source.python"]);
+      expect(tokens[4][6].value).toBe(" ");
+      expect(tokens[4][6].scopes).toEqual(["source.python"]);
+      expect(tokens[4][7].value).toBe("as");
+      expect(tokens[4][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][8].value).toBe(" ");
+      expect(tokens[4][8].scopes).toEqual(["source.python"]);
+      expect(tokens[4][9].value).toBe("d");
+      expect(tokens[4][9].scopes).toEqual(["source.python"]);
+      expect(tokens[4][10].value).toBe(",");
+      expect(tokens[4][10].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[4][11].value).toBe(" ");
+      expect(tokens[4][11].scopes).toEqual(["source.python"]);
+      expect(tokens[4][12].value).toBe("c");
+      expect(tokens[4][12].scopes).toEqual(["source.python"]);
+      expect(tokens[4][13].value).toBe(":");
+      expect(tokens[4][13].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[5][0].value).toBe("            ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("await");
+      expect(tokens[5][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[5][2].value).toBe(" ");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][3].value).toBe("func");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[5][4].value).toBe("(");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[5][5].value).toBe("a");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[5][6].value).toBe(",");
+      expect(tokens[5][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[5][7].value).toBe(" ");
+      expect(tokens[5][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[5][8].value).toBe("b");
+      expect(tokens[5][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[5][9].value).toBe("=");
+      expect(tokens[5][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[5][10].value).toBe("1");
+      expect(tokens[5][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[5][11].value).toBe(")");
+      expect(tokens[5][11].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/functions/async2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("async = await = 2")
+      expect(tokens[0][0].value).toBe("async");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("await");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("=");
+      expect(tokens[0][6].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("2");
+      expect(tokens[0][8].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/functions/async3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("casync def foo(): pass")
+      expect(tokens[0][0].value).toBe("casync");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("def");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][4].value).toBe("foo");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][5].value).toBe("(");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][6].value).toBe(")");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][7].value).toBe(":");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe("pass");
+      expect(tokens[0][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decl1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def myfunc(self,            # gotta have self\n           param1=\"value\",  # values are cool\n           param2=True,     # or False, whatever\n           **kwargs):       # you never know\n    pass")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("myfunc");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe("self");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python","variable.parameter.function.language.special.self.python"]);
+      expect(tokens[0][5].value).toBe(",");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][6].value).toBe("            ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][7].value).toBe("#");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][8].value).toBe(" gotta have self");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("           ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][1].value).toBe("param1");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[1][3].value).toBe("\"");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][4].value).toBe("value");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python"]);
+      expect(tokens[1][5].value).toBe("\"");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][6].value).toBe(",");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[1][7].value).toBe("  ");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][8].value).toBe("#");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][9].value).toBe(" values are cool");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python"]);
+      expect(tokens[2][0].value).toBe("           ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[2][1].value).toBe("param2");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[2][3].value).toBe("True");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.language.python"]);
+      expect(tokens[2][4].value).toBe(",");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[2][5].value).toBe("     ");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[2][6].value).toBe("#");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][7].value).toBe(" or False, whatever");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python"]);
+      expect(tokens[3][0].value).toBe("           ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][1].value).toBe("**");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.unpacking.parameter.python"]);
+      expect(tokens[3][2].value).toBe("kwargs");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[3][3].value).toBe(")");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[3][4].value).toBe(":");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[3][5].value).toBe("       ");
+      expect(tokens[3][5].scopes).toEqual(["source.python"]);
+      expect(tokens[3][6].value).toBe("#");
+      expect(tokens[3][6].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][7].value).toBe(" you never know");
+      expect(tokens[3][7].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("pass");
+      expect(tokens[4][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decl10.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def foo(True): True")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe("True");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.illegal.name.python"]);
+      expect(tokens[0][5].value).toBe(")");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][6].value).toBe(":");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("True");
+      expect(tokens[0][8].scopes).toEqual(["source.python","constant.language.python"]);
+    });
+
+  it("test/functions/decl11.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# testing annotations split over multiple lines\ndef foo(a:('abc' 'def')==123, boo: 'abc'\n\n                         'def' == foo(n(m=0)))")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" testing annotations split over multiple lines");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("foo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe("a");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.annotation.python"]);
+      expect(tokens[1][6].value).toBe("(");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[1][7].value).toBe("'");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][8].value).toBe("abc");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python"]);
+      expect(tokens[1][9].value).toBe("'");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][10].value).toBe(" ");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][11].value).toBe("'");
+      expect(tokens[1][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][12].value).toBe("def");
+      expect(tokens[1][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python"]);
+      expect(tokens[1][13].value).toBe("'");
+      expect(tokens[1][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][14].value).toBe(")");
+      expect(tokens[1][14].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[1][15].value).toBe("==");
+      expect(tokens[1][15].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.comparison.python"]);
+      expect(tokens[1][16].value).toBe("123");
+      expect(tokens[1][16].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[1][17].value).toBe(",");
+      expect(tokens[1][17].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[1][18].value).toBe(" ");
+      expect(tokens[1][18].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][19].value).toBe("boo");
+      expect(tokens[1][19].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[1][20].value).toBe(":");
+      expect(tokens[1][20].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.annotation.python"]);
+      expect(tokens[1][21].value).toBe(" ");
+      expect(tokens[1][21].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][22].value).toBe("'");
+      expect(tokens[1][22].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][23].value).toBe("abc");
+      expect(tokens[1][23].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python"]);
+      expect(tokens[1][24].value).toBe("'");
+      expect(tokens[1][24].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][0].value).toBe("                         ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][1].value).toBe("'");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe("def");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python"]);
+      expect(tokens[3][3].value).toBe("'");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][4].value).toBe(" ");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][5].value).toBe("==");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.comparison.python"]);
+      expect(tokens[3][6].value).toBe(" ");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][7].value).toBe("foo");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[3][8].value).toBe("(");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][9].value).toBe("n");
+      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[3][10].value).toBe("(");
+      expect(tokens[3][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][11].value).toBe("m");
+      expect(tokens[3][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][12].value).toBe("=");
+      expect(tokens[3][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][13].value).toBe("0");
+      expect(tokens[3][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[3][14].value).toBe(")");
+      expect(tokens[3][14].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][15].value).toBe(")");
+      expect(tokens[3][15].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][16].value).toBe(")");
+      expect(tokens[3][16].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+    });
+
+  it("test/functions/decl12.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def get_streaks(s) \\\n    -> 'spam': pass")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("get_streaks");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe("s");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][5].value).toBe(")");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][7].value).toBe("\\");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[0][8].value).toBe("");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][1].value).toBe("->");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python","punctuation.separator.annotation.result.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][3].value).toBe("'");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][4].value).toBe("spam");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","string.quoted.single.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][6].value).toBe(":");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][7].value).toBe(" ");
+      expect(tokens[1][7].scopes).toEqual(["source.python"]);
+      expect(tokens[1][8].value).toBe("pass");
+      expect(tokens[1][8].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decl13.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def foo()\n    -> notOK:\n    pass")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("->");
+      expect(tokens[1][1].scopes).toEqual(["source.python","invalid.illegal.annotation.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("notOK");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe(":");
+      expect(tokens[1][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("pass");
+      expect(tokens[2][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decl14.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# testing comments in function definition\ndef foo(    # before args\n    a=42,   # between\n            # args\n    b=      # in args\n      24,\n    d       # before '='\n     =99,\n    e\n    )       # incomplete definition, missing COLON, you're probably typing it\n    # pre docstring\n    '''Docstring'''\n    # post docstring\n\ndef bar(): return 1")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" testing comments in function definition");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("foo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe("    ");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][5].value).toBe("#");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][6].value).toBe(" before args");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[2][1].value).toBe("a");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[2][3].value).toBe("42");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[2][4].value).toBe(",");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[2][5].value).toBe("   ");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[2][6].value).toBe("#");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][7].value).toBe(" between");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python"]);
+      expect(tokens[3][0].value).toBe("            ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][1].value).toBe("#");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][2].value).toBe(" args");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[4][1].value).toBe("b");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[4][2].value).toBe("=");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[4][3].value).toBe("      ");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[4][4].value).toBe("#");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[4][5].value).toBe(" in args");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python"]);
+      expect(tokens[5][0].value).toBe("      ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[5][1].value).toBe("24");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[5][2].value).toBe(",");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[6][0].value).toBe("    ");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[6][1].value).toBe("d");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[6][2].value).toBe("       ");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[6][3].value).toBe("#");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[6][4].value).toBe(" before '='");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","comment.line.number-sign.python"]);
+      expect(tokens[7][0].value).toBe("     ");
+      expect(tokens[7][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[7][1].value).toBe("=");
+      expect(tokens[7][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[7][2].value).toBe("99");
+      expect(tokens[7][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[7][3].value).toBe(",");
+      expect(tokens[7][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[8][0].value).toBe("    ");
+      expect(tokens[8][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[8][1].value).toBe("e");
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[9][0].value).toBe("    ");
+      expect(tokens[9][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[9][1].value).toBe(")");
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[9][2].value).toBe("       ");
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[9][3].value).toBe("#");
+      expect(tokens[9][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[9][4].value).toBe(" incomplete definition, missing COLON, you're probably typing it");
+      expect(tokens[9][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[10][0].value).toBe("    ");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe("#");
+      expect(tokens[10][1].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[10][2].value).toBe(" pre docstring");
+      expect(tokens[10][2].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[11][0].value).toBe("    ");
+      expect(tokens[11][0].scopes).toEqual(["source.python"]);
+      expect(tokens[11][1].value).toBe("'''");
+      expect(tokens[11][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[11][2].value).toBe("Docstring");
+      expect(tokens[11][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[11][3].value).toBe("'''");
+      expect(tokens[11][3].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[12][0].value).toBe("    ");
+      expect(tokens[12][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][1].value).toBe("#");
+      expect(tokens[12][1].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[12][2].value).toBe(" post docstring");
+      expect(tokens[12][2].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[13][0].value).toBe("");
+      expect(tokens[13][0].scopes).toEqual(["source.python"]);
+      expect(tokens[14][0].value).toBe("def");
+      expect(tokens[14][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[14][1].value).toBe(" ");
+      expect(tokens[14][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[14][2].value).toBe("bar");
+      expect(tokens[14][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[14][3].value).toBe("(");
+      expect(tokens[14][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[14][4].value).toBe(")");
+      expect(tokens[14][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[14][5].value).toBe(":");
+      expect(tokens[14][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[14][6].value).toBe(" ");
+      expect(tokens[14][6].scopes).toEqual(["source.python"]);
+      expect(tokens[14][7].value).toBe("return");
+      expect(tokens[14][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[14][8].value).toBe(" ");
+      expect(tokens[14][8].scopes).toEqual(["source.python"]);
+      expect(tokens[14][9].value).toBe("1");
+      expect(tokens[14][9].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/functions/decl2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def result_annot(lambda, lambda=) -> qqq[None]:\n    pass")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("result_annot");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe("lambda");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][5].value).toBe(", ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][6].value).toBe("lambda");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.control.flow.python"]);
+      expect(tokens[0][7].value).toBe("=");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[0][8].value).toBe(")");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][10].value).toBe("->");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.function.python","punctuation.separator.annotation.result.python"]);
+      expect(tokens[0][11].value).toBe(" ");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][12].value).toBe("qqq");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function.python","meta.item-access.python"]);
+      expect(tokens[0][13].value).toBe("[");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.function.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][14].value).toBe("None");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.function.python","meta.item-access.python","meta.item-access.arguments.python","constant.language.python"]);
+      expect(tokens[0][15].value).toBe("]");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.function.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][16].value).toBe(":");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("pass");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decl3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# testing annotations split over multiple lines\ndef __init__(self, a:('abc' 'def')=123, boo: 'abc'\n\n                         'def' = foo(n(m=0), baz=\n                            13)) -> 123 : 123")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" testing annotations split over multiple lines");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("__init__");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","support.function.magic.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe("self");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python","variable.parameter.function.language.special.self.python"]);
+      expect(tokens[1][5].value).toBe(",");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][7].value).toBe("a");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[1][8].value).toBe(":");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.annotation.python"]);
+      expect(tokens[1][9].value).toBe("(");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[1][10].value).toBe("'");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][11].value).toBe("abc");
+      expect(tokens[1][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python"]);
+      expect(tokens[1][12].value).toBe("'");
+      expect(tokens[1][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][13].value).toBe(" ");
+      expect(tokens[1][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][14].value).toBe("'");
+      expect(tokens[1][14].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][15].value).toBe("def");
+      expect(tokens[1][15].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python"]);
+      expect(tokens[1][16].value).toBe("'");
+      expect(tokens[1][16].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][17].value).toBe(")");
+      expect(tokens[1][17].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[1][18].value).toBe("=");
+      expect(tokens[1][18].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][19].value).toBe("123");
+      expect(tokens[1][19].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[1][20].value).toBe(",");
+      expect(tokens[1][20].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[1][21].value).toBe(" ");
+      expect(tokens[1][21].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][22].value).toBe("boo");
+      expect(tokens[1][22].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[1][23].value).toBe(":");
+      expect(tokens[1][23].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.annotation.python"]);
+      expect(tokens[1][24].value).toBe(" ");
+      expect(tokens[1][24].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[1][25].value).toBe("'");
+      expect(tokens[1][25].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][26].value).toBe("abc");
+      expect(tokens[1][26].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python"]);
+      expect(tokens[1][27].value).toBe("'");
+      expect(tokens[1][27].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][0].value).toBe("                         ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][1].value).toBe("'");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe("def");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python"]);
+      expect(tokens[3][3].value).toBe("'");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][4].value).toBe(" ");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][5].value).toBe("=");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][6].value).toBe(" ");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][7].value).toBe("foo");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[3][8].value).toBe("(");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][9].value).toBe("n");
+      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[3][10].value).toBe("(");
+      expect(tokens[3][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][11].value).toBe("m");
+      expect(tokens[3][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][12].value).toBe("=");
+      expect(tokens[3][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][13].value).toBe("0");
+      expect(tokens[3][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[3][14].value).toBe(")");
+      expect(tokens[3][14].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][15].value).toBe(",");
+      expect(tokens[3][15].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[3][16].value).toBe(" ");
+      expect(tokens[3][16].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][17].value).toBe("baz");
+      expect(tokens[3][17].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][18].value).toBe("=");
+      expect(tokens[3][18].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][0].value).toBe("                            ");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[4][1].value).toBe("13");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[4][2].value).toBe(")");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[4][3].value).toBe(")");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[4][4].value).toBe(" ");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[4][5].value).toBe("->");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.function.python","punctuation.separator.annotation.result.python"]);
+      expect(tokens[4][6].value).toBe(" ");
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[4][7].value).toBe("123");
+      expect(tokens[4][7].scopes).toEqual(["source.python","meta.function.python","constant.numeric.dec.python"]);
+      expect(tokens[4][8].value).toBe(" ");
+      expect(tokens[4][8].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[4][9].value).toBe(":");
+      expect(tokens[4][9].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[4][10].value).toBe(" ");
+      expect(tokens[4][10].scopes).toEqual(["source.python"]);
+      expect(tokens[4][11].value).toBe("123");
+      expect(tokens[4][11].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/functions/decl4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# testing annotations split over multiple lines\ndef some_func(a:\n                 lambda x=None:\n                    {key: val\n                        for key, val in\n                            (x if x is not None else [])\n                    }=42):")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" testing annotations split over multiple lines");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("some_func");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe("a");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.annotation.python"]);
+      expect(tokens[2][0].value).toBe("                 ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[2][1].value).toBe("lambda");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[2][3].value).toBe("x");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[2][4].value).toBe("=");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.lambda-function.python","meta.function.lambda.parameters.python","keyword.operator.python"]);
+      expect(tokens[2][5].value).toBe("None");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.lambda-function.python","meta.function.lambda.parameters.python","constant.language.python"]);
+      expect(tokens[2][6].value).toBe(":");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[3][0].value).toBe("                    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][1].value).toBe("{");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[3][2].value).toBe("key");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][3].value).toBe(":");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.dict.python"]);
+      expect(tokens[3][4].value).toBe(" ");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][5].value).toBe("val");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[4][0].value).toBe("                        ");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[4][1].value).toBe("for");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.control.flow.python"]);
+      expect(tokens[4][2].value).toBe(" ");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[4][3].value).toBe("key");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[4][4].value).toBe(",");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.element.python"]);
+      expect(tokens[4][5].value).toBe(" ");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[4][6].value).toBe("val");
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[4][7].value).toBe(" ");
+      expect(tokens[4][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[4][8].value).toBe("in");
+      expect(tokens[4][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.logical.python"]);
+      expect(tokens[5][0].value).toBe("                            ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[5][1].value).toBe("(");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[5][2].value).toBe("x");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[5][3].value).toBe(" ");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[5][4].value).toBe("if");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.control.flow.python"]);
+      expect(tokens[5][5].value).toBe(" ");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[5][6].value).toBe("x");
+      expect(tokens[5][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[5][7].value).toBe(" ");
+      expect(tokens[5][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[5][8].value).toBe("is");
+      expect(tokens[5][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.logical.python"]);
+      expect(tokens[5][9].value).toBe(" ");
+      expect(tokens[5][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[5][10].value).toBe("not");
+      expect(tokens[5][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.logical.python"]);
+      expect(tokens[5][11].value).toBe(" ");
+      expect(tokens[5][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[5][12].value).toBe("None");
+      expect(tokens[5][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.language.python"]);
+      expect(tokens[5][13].value).toBe(" ");
+      expect(tokens[5][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[5][14].value).toBe("else");
+      expect(tokens[5][14].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.control.flow.python"]);
+      expect(tokens[5][15].value).toBe(" ");
+      expect(tokens[5][15].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[5][16].value).toBe("[");
+      expect(tokens[5][16].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[5][17].value).toBe("]");
+      expect(tokens[5][17].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.list.end.python"]);
+      expect(tokens[5][18].value).toBe(")");
+      expect(tokens[5][18].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[6][0].value).toBe("                    ");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[6][1].value).toBe("}");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[6][2].value).toBe("=");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.assignment.python"]);
+      expect(tokens[6][3].value).toBe("42");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[6][4].value).toBe(")");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[6][5].value).toBe(":");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+    });
+
+  it("test/functions/decl5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def f()->123:pass")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("f");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][5].value).toBe("->");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","punctuation.separator.annotation.result.python"]);
+      expect(tokens[0][6].value).toBe("123");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.python","constant.numeric.dec.python"]);
+      expect(tokens[0][7].value).toBe(":");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[0][8].value).toBe("pass");
+      expect(tokens[0][8].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decl6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def True(): pass\ndef None(): pass\ndef False(): pass")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("True");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","keyword.illegal.name.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe("pass");
+      expect(tokens[0][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("None");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","keyword.illegal.name.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe("pass");
+      expect(tokens[1][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][0].value).toBe("def");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][2].value).toBe("False");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","keyword.illegal.name.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[2][4].value).toBe(")");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[2][5].value).toBe(":");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[2][6].value).toBe(" ");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][7].value).toBe("pass");
+      expect(tokens[2][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decl7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def foo(*, a): pass\ndef foo(*a): pass\ndef foo(**a): pass")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe("*");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.unpacking.parameter.python"]);
+      expect(tokens[0][5].value).toBe(", ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][6].value).toBe("a");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][7].value).toBe(")");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][8].value).toBe(":");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("pass");
+      expect(tokens[0][10].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("foo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe("*");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.unpacking.parameter.python"]);
+      expect(tokens[1][5].value).toBe("a");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[1][6].value).toBe(")");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][7].value).toBe(":");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][8].value).toBe(" ");
+      expect(tokens[1][8].scopes).toEqual(["source.python"]);
+      expect(tokens[1][9].value).toBe("pass");
+      expect(tokens[1][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][0].value).toBe("def");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][2].value).toBe("foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[2][4].value).toBe("**");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.unpacking.parameter.python"]);
+      expect(tokens[2][5].value).toBe("a");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[2][6].value).toBe(")");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[2][7].value).toBe(":");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[2][8].value).toBe(" ");
+      expect(tokens[2][8].scopes).toEqual(["source.python"]);
+      expect(tokens[2][9].value).toBe("pass");
+      expect(tokens[2][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decl8.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def foo(a=1**1, *b:3*2=1*2, **a=1*2**3): pass")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe("a");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][5].value).toBe("=");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[0][6].value).toBe("1");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[0][7].value).toBe("**");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][8].value).toBe("1");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[0][9].value).toBe(",");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][11].value).toBe("*");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.unpacking.parameter.python"]);
+      expect(tokens[0][12].value).toBe("b");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][13].value).toBe(":");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.annotation.python"]);
+      expect(tokens[0][14].value).toBe("3");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[0][15].value).toBe("*");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][16].value).toBe("2");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[0][17].value).toBe("=");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][18].value).toBe("1");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[0][19].value).toBe("*");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][20].value).toBe("2");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[0][21].value).toBe(",");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][22].value).toBe(" ");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][23].value).toBe("**");
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.unpacking.parameter.python"]);
+      expect(tokens[0][24].value).toBe("a");
+      expect(tokens[0][24].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][25].value).toBe("=");
+      expect(tokens[0][25].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[0][26].value).toBe("1");
+      expect(tokens[0][26].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[0][27].value).toBe("*");
+      expect(tokens[0][27].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][28].value).toBe("2");
+      expect(tokens[0][28].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[0][29].value).toBe("**");
+      expect(tokens[0][29].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][30].value).toBe("3");
+      expect(tokens[0][30].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[0][31].value).toBe(")");
+      expect(tokens[0][31].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][32].value).toBe(":");
+      expect(tokens[0][32].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[0][33].value).toBe(" ");
+      expect(tokens[0][33].scopes).toEqual(["source.python"]);
+      expect(tokens[0][34].value).toBe("pass");
+      expect(tokens[0][34].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decl9.py", 
+    function() {
+      tokens = grammar.tokenizeLines("cdef foo(): pass")
+      expect(tokens[0][0].value).toBe("cdef");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe("pass");
+      expect(tokens[0][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decorators1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("@some_decorator # with comment\n@some.class.decorator\n@some_decorator(1)\n@some.decorator   (1, 3)\n@some_decorator(a=2, b={'q': 42}, **kwargs)\n@classmethod\ndef decorated(a): pass")
+      expect(tokens[0][0].value).toBe("@");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][1].value).toBe("some_decorator");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][2].value).toBe(" ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][3].value).toBe("#");
+      expect(tokens[0][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][4].value).toBe(" with comment");
+      expect(tokens[0][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("@");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][1].value).toBe("some");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][2].value).toBe(".");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][3].value).toBe("class");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.decorator.python","keyword.control.flow.python"]);
+      expect(tokens[1][4].value).toBe(".");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][5].value).toBe("decorator");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][0].value).toBe("@");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][1].value).toBe("some_decorator");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][2].value).toBe("(");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][3].value).toBe("1");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[2][4].value).toBe(")");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][0].value).toBe("@");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][1].value).toBe("some");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][2].value).toBe(".");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][3].value).toBe("decorator");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][4].value).toBe("   ");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[3][5].value).toBe("(");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][6].value).toBe("1");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[3][7].value).toBe(",");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[3][8].value).toBe(" ");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][9].value).toBe("3");
+      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[3][10].value).toBe(")");
+      expect(tokens[3][10].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[4][0].value).toBe("@");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][1].value).toBe("some_decorator");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][2].value).toBe("(");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[4][3].value).toBe("a");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[4][4].value).toBe("=");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][5].value).toBe("2");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[4][6].value).toBe(",");
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[4][7].value).toBe(" ");
+      expect(tokens[4][7].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python"]);
+      expect(tokens[4][8].value).toBe("b");
+      expect(tokens[4][8].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[4][9].value).toBe("=");
+      expect(tokens[4][9].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][10].value).toBe("{");
+      expect(tokens[4][10].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[4][11].value).toBe("'");
+      expect(tokens[4][11].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][12].value).toBe("q");
+      expect(tokens[4][12].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[4][13].value).toBe("'");
+      expect(tokens[4][13].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][14].value).toBe(":");
+      expect(tokens[4][14].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","punctuation.separator.dict.python"]);
+      expect(tokens[4][15].value).toBe(" ");
+      expect(tokens[4][15].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python"]);
+      expect(tokens[4][16].value).toBe("42");
+      expect(tokens[4][16].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[4][17].value).toBe("}");
+      expect(tokens[4][17].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[4][18].value).toBe(",");
+      expect(tokens[4][18].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[4][19].value).toBe(" ");
+      expect(tokens[4][19].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python"]);
+      expect(tokens[4][20].value).toBe("**");
+      expect(tokens[4][20].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[4][21].value).toBe("kwargs");
+      expect(tokens[4][21].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python"]);
+      expect(tokens[4][22].value).toBe(")");
+      expect(tokens[4][22].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[5][0].value).toBe("@");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[5][1].value).toBe("classmethod");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function.decorator.python","support.type.python"]);
+      expect(tokens[6][0].value).toBe("def");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[6][2].value).toBe("decorated");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[6][3].value).toBe("(");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[6][4].value).toBe("a");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[6][5].value).toBe(")");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[6][6].value).toBe(":");
+      expect(tokens[6][6].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[6][7].value).toBe(" ");
+      expect(tokens[6][7].scopes).toEqual(["source.python"]);
+      expect(tokens[6][8].value).toBe("pass");
+      expect(tokens[6][8].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decorators2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("@ f . bar . a . b\ndef foo(): pass")
+      expect(tokens[0][0].value).toBe("@");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][2].value).toBe("f");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][4].value).toBe(".");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][6].value).toBe("bar");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][8].value).toBe(".");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][10].value).toBe("a");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][11].value).toBe(" ");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][12].value).toBe(".");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][13].value).toBe(" ");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][14].value).toBe("b");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("foo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe("pass");
+      expect(tokens[1][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decorators3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("@ f . bar (baz = 1)\ndef foo(): pass")
+      expect(tokens[0][0].value).toBe("@");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][2].value).toBe("f");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][4].value).toBe(".");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][6].value).toBe("bar");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][8].value).toBe("(");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][9].value).toBe("baz");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][11].value).toBe("=");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][12].value).toBe(" ");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][13].value).toBe("1");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][14].value).toBe(")");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("foo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe("pass");
+      expect(tokens[1][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decorators4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("@a.b.c.None.z\ndef foo(): pass")
+      expect(tokens[0][0].value).toBe("@");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][1].value).toBe("a");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][2].value).toBe(".");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][3].value).toBe("b");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][4].value).toBe(".");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][5].value).toBe("c");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][6].value).toBe(".");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][7].value).toBe("None");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.decorator.python","keyword.illegal.name.python"]);
+      expect(tokens[0][8].value).toBe(".");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][9].value).toBe("z");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("foo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe("pass");
+      expect(tokens[1][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decorators5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("@a. \\\n  b  .  \\\n   c.None.z \\\n    baz(q=1)\n@foo.ok\ndef foo(): pass")
+      expect(tokens[0][0].value).toBe("@");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][1].value).toBe("a");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][2].value).toBe(".");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][4].value).toBe("\\");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[0][5].value).toBe("");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[1][0].value).toBe("  ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[1][1].value).toBe("b");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][2].value).toBe("  ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[1][3].value).toBe(".");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][4].value).toBe("  ");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[1][5].value).toBe("\\");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][6].value).toBe("");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[2][0].value).toBe("   ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[2][1].value).toBe("c");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][2].value).toBe(".");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][3].value).toBe("None");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.decorator.python","keyword.illegal.name.python"]);
+      expect(tokens[2][4].value).toBe(".");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][5].value).toBe("z");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][6].value).toBe(" ");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[2][7].value).toBe("\\");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[2][8].value).toBe("");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[3][1].value).toBe("baz");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][2].value).toBe("(");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][3].value).toBe("q");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][4].value).toBe("=");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][5].value).toBe("1");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[3][6].value).toBe(")");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[4][0].value).toBe("@");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][1].value).toBe("foo");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][2].value).toBe(".");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][3].value).toBe("ok");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[5][0].value).toBe("def");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[5][1].value).toBe(" ");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[5][2].value).toBe("foo");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[5][3].value).toBe("(");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[5][4].value).toBe(")");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[5][5].value).toBe(":");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[5][6].value).toBe(" ");
+      expect(tokens[5][6].scopes).toEqual(["source.python"]);
+      expect(tokens[5][7].value).toBe("pass");
+      expect(tokens[5][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decorators6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("@a.   b  .  \\\n   c.None.z(foo=BAR). \\\n       baz[1:2]\n@foo.class.bar[]\n@foo.ok '''\ndef foo(): pass")
+      expect(tokens[0][0].value).toBe("@");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][1].value).toBe("a");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][2].value).toBe(".");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][3].value).toBe("   ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][4].value).toBe("b");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][5].value).toBe("  ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][6].value).toBe(".");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][7].value).toBe("  ");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[0][8].value).toBe("\\");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[0][9].value).toBe("");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[1][0].value).toBe("   ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[1][1].value).toBe("c");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][2].value).toBe(".");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][3].value).toBe("None");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.decorator.python","keyword.illegal.name.python"]);
+      expect(tokens[1][4].value).toBe(".");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][5].value).toBe("z");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][6].value).toBe("(");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][7].value).toBe("foo");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[1][8].value).toBe("=");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][9].value).toBe("BAR");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function.decorator.python","meta.function-call.arguments.python","constant.other.caps.python"]);
+      expect(tokens[1][10].value).toBe(")");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][11].value).toBe(". \\");
+      expect(tokens[1][11].scopes).toEqual(["source.python","meta.function.decorator.python","invalid.illegal.decorator.python"]);
+      expect(tokens[2][0].value).toBe("       ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("baz");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.item-access.python"]);
+      expect(tokens[2][2].value).toBe("[");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][3].value).toBe("1");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[2][4].value).toBe(":");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","punctuation.separator.slice.python"]);
+      expect(tokens[2][5].value).toBe("2");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[2][6].value).toBe("]");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][0].value).toBe("@");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][1].value).toBe("foo");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][2].value).toBe(".");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][3].value).toBe("class");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.decorator.python","keyword.control.flow.python"]);
+      expect(tokens[3][4].value).toBe(".");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][5].value).toBe("bar");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][6].value).toBe("[]");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function.decorator.python","invalid.illegal.decorator.python","invalid.illegal.decorator.python"]);
+      expect(tokens[4][0].value).toBe("@");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][1].value).toBe("foo");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][2].value).toBe(".");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][3].value).toBe("ok");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][4].value).toBe(" ");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function.decorator.python","invalid.illegal.decorator.python"]);
+      expect(tokens[4][5].value).toBe("'''");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.function.decorator.python","invalid.illegal.decorator.python","invalid.illegal.decorator.python"]);
+      expect(tokens[5][0].value).toBe("def");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[5][1].value).toBe(" ");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[5][2].value).toBe("foo");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[5][3].value).toBe("(");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[5][4].value).toBe(")");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[5][5].value).toBe(":");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[5][6].value).toBe(" ");
+      expect(tokens[5][6].scopes).toEqual(["source.python"]);
+      expect(tokens[5][7].value).toBe("pass");
+      expect(tokens[5][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decorators7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# this is testing trailing whitespace after the decorator\n# DO NOT DELETE TRAILING WHITESTAPCE IN THIS FILE\n@foo    \n@foo()    \n@bar\t\n@bar()\t\n@bar() illegal # legal\n@bar():   \ndef baz(): pass")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" this is testing trailing whitespace after the decorator");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("#");
+      expect(tokens[1][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][1].value).toBe(" DO NOT DELETE TRAILING WHITESTAPCE IN THIS FILE");
+      expect(tokens[1][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[2][0].value).toBe("@");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][1].value).toBe("foo");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][2].value).toBe("    ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[3][0].value).toBe("@");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][1].value).toBe("foo");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][2].value).toBe("(");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][3].value).toBe(")");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][4].value).toBe("    ");
+      expect(tokens[3][4].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("@");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][1].value).toBe("bar");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][2].value).toBe("\t");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[5][0].value).toBe("@");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[5][1].value).toBe("bar");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[5][2].value).toBe("(");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[5][3].value).toBe(")");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[5][4].value).toBe("\t");
+      expect(tokens[5][4].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("@");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[6][1].value).toBe("bar");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[6][2].value).toBe("(");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[6][3].value).toBe(")");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[6][4].value).toBe(" illegal");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function.decorator.python","invalid.illegal.decorator.python"]);
+      expect(tokens[6][5].value).toBe(" ");
+      expect(tokens[6][5].scopes).toEqual(["source.python"]);
+      expect(tokens[6][6].value).toBe("#");
+      expect(tokens[6][6].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[6][7].value).toBe(" legal");
+      expect(tokens[6][7].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[7][0].value).toBe("@");
+      expect(tokens[7][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[7][1].value).toBe("bar");
+      expect(tokens[7][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[7][2].value).toBe("(");
+      expect(tokens[7][2].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[7][3].value).toBe(")");
+      expect(tokens[7][3].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[7][4].value).toBe(":");
+      expect(tokens[7][4].scopes).toEqual(["source.python","meta.function.decorator.python","invalid.illegal.decorator.python"]);
+      expect(tokens[7][5].value).toBe("   ");
+      expect(tokens[7][5].scopes).toEqual(["source.python"]);
+      expect(tokens[8][0].value).toBe("def");
+      expect(tokens[8][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[8][1].value).toBe(" ");
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[8][2].value).toBe("baz");
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[8][3].value).toBe("(");
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[8][4].value).toBe(")");
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[8][5].value).toBe(":");
+      expect(tokens[8][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[8][6].value).toBe(" ");
+      expect(tokens[8][6].scopes).toEqual(["source.python"]);
+      expect(tokens[8][7].value).toBe("pass");
+      expect(tokens[8][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/decorators8.py", 
+    function() {
+      tokens = grammar.tokenizeLines("@deco().abc  # SyntaxError: invalid syntax\ndef foo(): pass")
+      expect(tokens[0][0].value).toBe("@");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][1].value).toBe("deco");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][2].value).toBe("(");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][3].value).toBe(")");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][4].value).toBe(".abc");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","invalid.illegal.decorator.python"]);
+      expect(tokens[0][5].value).toBe("  ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("#");
+      expect(tokens[0][6].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][7].value).toBe(" SyntaxError: invalid syntax");
+      expect(tokens[0][7].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("foo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe("pass");
+      expect(tokens[1][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/lambda1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# That's how we want it:\nlll(lambda)")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" That's how we want it:");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("lll");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][1].value).toBe("(");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][2].value).toBe("lambda");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","storage.type.function.lambda.python"]);
+      expect(tokens[1][3].value).toBe(")");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/functions/lambda2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("lll(lambda=1)")
+      expect(tokens[0][0].value).toBe("lll");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][2].value).toBe("lambda");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.control.flow.python"]);
+      expect(tokens[0][3].value).toBe("=");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][4].value).toBe("1");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][5].value).toBe(")");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/functions/lambda3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("anon = lambda lambda: 42")
+      expect(tokens[0][0].value).toBe("anon");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("lambda");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][6].value).toBe("lambda");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][7].value).toBe(":");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe("42");
+      expect(tokens[0][9].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/functions/lambda4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("lambda a : 1")
+      expect(tokens[0][0].value).toBe("lambda");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][2].value).toBe("a");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][4].value).toBe(":");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("1");
+      expect(tokens[0][6].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/functions/lambda5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("anon = lambda -> qqq[None]: None\ndef f(): return 1 # this line should not break")
+      expect(tokens[0][0].value).toBe("anon");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("lambda");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][6].value).toBe("->");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","invalid.illegal.annotation.python"]);
+      expect(tokens[0][7].value).toBe(" qqq[None]");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][8].value).toBe(":");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("None");
+      expect(tokens[0][10].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("f");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe("return");
+      expect(tokens[1][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][8].value).toBe(" ");
+      expect(tokens[1][8].scopes).toEqual(["source.python"]);
+      expect(tokens[1][9].value).toBe("1");
+      expect(tokens[1][9].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][10].value).toBe(" ");
+      expect(tokens[1][10].scopes).toEqual(["source.python"]);
+      expect(tokens[1][11].value).toBe("#");
+      expect(tokens[1][11].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][12].value).toBe(" this line should not break");
+      expect(tokens[1][12].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/functions/lambda6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("anon = lambda a=123, c={'': 555}, \\\n              d=toow(24): None")
+      expect(tokens[0][0].value).toBe("anon");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("lambda");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][6].value).toBe("a");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][7].value).toBe("=");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","keyword.operator.python"]);
+      expect(tokens[0][8].value).toBe("123");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[0][9].value).toBe(",");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][11].value).toBe("c");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][12].value).toBe("=");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","keyword.operator.python"]);
+      expect(tokens[0][13].value).toBe("{");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[0][14].value).toBe("'");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][15].value).toBe("'");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][16].value).toBe(":");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.separator.dict.python"]);
+      expect(tokens[0][17].value).toBe(" ");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][18].value).toBe("555");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[0][19].value).toBe("}");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[0][20].value).toBe(",");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][21].value).toBe(" ");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][22].value).toBe("\\");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[0][23].value).toBe("");
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[1][0].value).toBe("              ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[1][1].value).toBe("d");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","keyword.operator.python"]);
+      expect(tokens[1][3].value).toBe("toow");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][4].value).toBe("(");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][5].value).toBe("24");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[1][6].value).toBe(")");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][7].value).toBe(":");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[1][8].value).toBe(" ");
+      expect(tokens[1][8].scopes).toEqual(["source.python"]);
+      expect(tokens[1][9].value).toBe("None");
+      expect(tokens[1][9].scopes).toEqual(["source.python","constant.language.python"]);
+    });
+
+  it("test/functions/lambda7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("anon = lambda a, c={'key':\n\n                                 555}, e=fff: None")
+      expect(tokens[0][0].value).toBe("anon");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("lambda");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][6].value).toBe("a");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][7].value).toBe(",");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][9].value).toBe("c");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][10].value).toBe("=");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","keyword.operator.python"]);
+      expect(tokens[0][11].value).toBe("{");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[0][12].value).toBe("'");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][13].value).toBe("key");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","string.quoted.single.python"]);
+      expect(tokens[0][14].value).toBe("'");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][15].value).toBe(":");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.separator.dict.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[2][0].value).toBe("                                 ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[2][1].value).toBe("555");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[2][2].value).toBe("}");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[2][3].value).toBe(",");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[2][4].value).toBe(" ");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[2][5].value).toBe("e");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[2][6].value).toBe("=");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","keyword.operator.python"]);
+      expect(tokens[2][7].value).toBe("fff");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[2][8].value).toBe(":");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[2][9].value).toBe(" ");
+      expect(tokens[2][9].scopes).toEqual(["source.python"]);
+      expect(tokens[2][10].value).toBe("None");
+      expect(tokens[2][10].scopes).toEqual(["source.python","constant.language.python"]);
+    });
+
+  it("test/functions/lambda8.py", 
+    function() {
+      tokens = grammar.tokenizeLines("anon = lambda a,\n              d=1: None\ndef foo(): pass")
+      expect(tokens[0][0].value).toBe("anon");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("lambda");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][6].value).toBe("a");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][7].value).toBe(",");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][8].value).toBe("");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.lambda-function.python"]);
+      expect(tokens[1][0].value).toBe("              ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("d");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe("1");
+      expect(tokens[1][3].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][4].value).toBe(":");
+      expect(tokens[1][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("None");
+      expect(tokens[1][6].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[2][0].value).toBe("def");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][2].value).toBe("foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[2][4].value).toBe(")");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[2][5].value).toBe(":");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[2][6].value).toBe(" ");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][7].value).toBe("pass");
+      expect(tokens[2][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/functions/lambda9.py", 
+    function() {
+      tokens = grammar.tokenizeLines("lambda *, b: b\nlambda *b: b\nlambda **b: b")
+      expect(tokens[0][0].value).toBe("lambda");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][2].value).toBe("*");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","keyword.operator.unpacking.parameter.python"]);
+      expect(tokens[0][3].value).toBe(", ");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][4].value).toBe("b");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][5].value).toBe(":");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe("b");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("lambda");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[1][2].value).toBe("*");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","keyword.operator.unpacking.parameter.python"]);
+      expect(tokens[1][3].value).toBe("b");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[1][4].value).toBe(":");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("b");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("lambda");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[2][2].value).toBe("**");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","keyword.operator.unpacking.parameter.python"]);
+      expect(tokens[2][3].value).toBe("b");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[2][4].value).toBe(":");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("b");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/illegals/backticks1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = `(1, `2`)`")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("`");
+      expect(tokens[0][4].scopes).toEqual(["source.python","invalid.deprecated.backtick.python"]);
+      expect(tokens[0][5].value).toBe("(");
+      expect(tokens[0][5].scopes).toEqual(["source.python","invalid.deprecated.backtick.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[0][6].value).toBe("1");
+      expect(tokens[0][6].scopes).toEqual(["source.python","invalid.deprecated.backtick.python","constant.numeric.dec.python"]);
+      expect(tokens[0][7].value).toBe(",");
+      expect(tokens[0][7].scopes).toEqual(["source.python","invalid.deprecated.backtick.python","punctuation.separator.element.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python","invalid.deprecated.backtick.python"]);
+      expect(tokens[0][9].value).toBe("`");
+      expect(tokens[0][9].scopes).toEqual(["source.python","invalid.deprecated.backtick.python","invalid.deprecated.backtick.python"]);
+      expect(tokens[0][10].value).toBe("2");
+      expect(tokens[0][10].scopes).toEqual(["source.python","invalid.deprecated.backtick.python","invalid.deprecated.backtick.python","constant.numeric.dec.python"]);
+      expect(tokens[0][11].value).toBe("`");
+      expect(tokens[0][11].scopes).toEqual(["source.python","invalid.deprecated.backtick.python","invalid.deprecated.backtick.python"]);
+      expect(tokens[0][12].value).toBe(")");
+      expect(tokens[0][12].scopes).toEqual(["source.python","invalid.deprecated.backtick.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[0][13].value).toBe("`");
+      expect(tokens[0][13].scopes).toEqual(["source.python","invalid.deprecated.backtick.python"]);
+    });
+
+  it("test/illegals/backticks2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = `\\\n123`\nprint a")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("`");
+      expect(tokens[0][4].scopes).toEqual(["source.python","invalid.deprecated.backtick.python"]);
+      expect(tokens[0][5].value).toBe("\\");
+      expect(tokens[0][5].scopes).toEqual(["source.python","invalid.deprecated.backtick.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[0][6].value).toBe("");
+      expect(tokens[0][6].scopes).toEqual(["source.python","invalid.deprecated.backtick.python"]);
+      expect(tokens[1][0].value).toBe("123");
+      expect(tokens[1][0].scopes).toEqual(["source.python","invalid.deprecated.backtick.python","constant.numeric.dec.python"]);
+      expect(tokens[1][1].value).toBe("`");
+      expect(tokens[1][1].scopes).toEqual(["source.python","invalid.deprecated.backtick.python"]);
+      expect(tokens[2][0].value).toBe("print");
+      expect(tokens[2][0].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("a");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/illegals/backticks3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = lambda `123`")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("lambda");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][6].value).toBe("`");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","invalid.deprecated.backtick.python"]);
+      expect(tokens[0][7].value).toBe("123");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","invalid.deprecated.backtick.python","constant.numeric.dec.python"]);
+      expect(tokens[0][8].value).toBe("`");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","invalid.deprecated.backtick.python"]);
+      expect(tokens[0][9].value).toBe("");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.lambda-function.python"]);
+    });
+
+  it("test/illegals/illegal1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("->\ndef f(): pass\n$\n?\na=$('.class').fuuuu(baz=1)\n# we recover just fine\nb = !some_ruby?\n# hey ;)")
+      expect(tokens[0][0].value).toBe("->");
+      expect(tokens[0][0].scopes).toEqual(["source.python","invalid.illegal.annotation.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("f");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe("pass");
+      expect(tokens[1][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][0].value).toBe("$");
+      expect(tokens[2][0].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[3][0].value).toBe("?");
+      expect(tokens[3][0].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[4][0].value).toBe("a");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("=");
+      expect(tokens[4][1].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][2].value).toBe("$");
+      expect(tokens[4][2].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[4][3].value).toBe("(");
+      expect(tokens[4][3].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[4][4].value).toBe("'");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][5].value).toBe(".class");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[4][6].value).toBe("'");
+      expect(tokens[4][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][7].value).toBe(")");
+      expect(tokens[4][7].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[4][8].value).toBe(".");
+      expect(tokens[4][8].scopes).toEqual(["source.python"]);
+      expect(tokens[4][9].value).toBe("fuuuu");
+      expect(tokens[4][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[4][10].value).toBe("(");
+      expect(tokens[4][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[4][11].value).toBe("baz");
+      expect(tokens[4][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[4][12].value).toBe("=");
+      expect(tokens[4][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][13].value).toBe("1");
+      expect(tokens[4][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[4][14].value).toBe(")");
+      expect(tokens[4][14].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[5][0].value).toBe("#");
+      expect(tokens[5][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[5][1].value).toBe(" we recover just fine");
+      expect(tokens[5][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[6][0].value).toBe("b");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].value).toBe("=");
+      expect(tokens[6][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[6][3].value).toBe(" ");
+      expect(tokens[6][3].scopes).toEqual(["source.python"]);
+      expect(tokens[6][4].value).toBe("!");
+      expect(tokens[6][4].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[6][5].value).toBe("some_ruby");
+      expect(tokens[6][5].scopes).toEqual(["source.python"]);
+      expect(tokens[6][6].value).toBe("?");
+      expect(tokens[6][6].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[7][0].value).toBe("#");
+      expect(tokens[7][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[7][1].value).toBe(" hey ;)");
+      expect(tokens[7][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/illegals/illegal2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a&&b||c\na &&= a\nb ||= c")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe("&&");
+      expect(tokens[0][1].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[0][2].value).toBe("b");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe("||");
+      expect(tokens[0][3].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[0][4].value).toBe("c");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("&&");
+      expect(tokens[1][2].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[1][3].value).toBe("=");
+      expect(tokens[1][3].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][4].value).toBe(" ");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][5].value).toBe("a");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("b");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("||");
+      expect(tokens[2][2].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[2][3].value).toBe("=");
+      expect(tokens[2][3].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][4].value).toBe(" ");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][5].value).toBe("c");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/linecont/linecont1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("1 + \\ sdgfsdf\ndef foo(): pass")
+      expect(tokens[0][0].value).toBe("1");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("+");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("\\");
+      expect(tokens[0][4].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("sdgfsdf");
+      expect(tokens[0][6].scopes).toEqual(["source.python","invalid.illegal.line.continuation.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("foo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe("pass");
+      expect(tokens[1][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/linecont/linecont2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("1 + \\\n 3")
+      expect(tokens[0][0].value).toBe("1");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("+");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("\\");
+      expect(tokens[0][4].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[0][5].value).toBe("");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe(" ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("3");
+      expect(tokens[1][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/numbers/complex1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("3.14j\n10.j\n10j\n.001j\n1e100j\n3.14e-10j")
+      expect(tokens[0][0].value).toBe("3.14");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[0][1].value).toBe("j");
+      expect(tokens[0][1].scopes).toEqual(["source.python","constant.numeric.float.python","storage.type.imaginary.number.python"]);
+      expect(tokens[1][0].value).toBe("10.");
+      expect(tokens[1][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[1][1].value).toBe("j");
+      expect(tokens[1][1].scopes).toEqual(["source.python","constant.numeric.float.python","storage.type.imaginary.number.python"]);
+      expect(tokens[2][0].value).toBe("10");
+      expect(tokens[2][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[2][1].value).toBe("j");
+      expect(tokens[2][1].scopes).toEqual(["source.python","constant.numeric.dec.python","storage.type.imaginary.number.python"]);
+      expect(tokens[3][0].value).toBe(".001");
+      expect(tokens[3][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[3][1].value).toBe("j");
+      expect(tokens[3][1].scopes).toEqual(["source.python","constant.numeric.float.python","storage.type.imaginary.number.python"]);
+      expect(tokens[4][0].value).toBe("1e100");
+      expect(tokens[4][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[4][1].value).toBe("j");
+      expect(tokens[4][1].scopes).toEqual(["source.python","constant.numeric.float.python","storage.type.imaginary.number.python"]);
+      expect(tokens[5][0].value).toBe("3.14e-10");
+      expect(tokens[5][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[5][1].value).toBe("j");
+      expect(tokens[5][1].scopes).toEqual(["source.python","constant.numeric.float.python","storage.type.imaginary.number.python"]);
+    });
+
+  it("test/numbers/complex2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("3.141_592j\n10_000.j\n10_000j\n.001_123j\n1e10_000j\n3.141_592e-10_000j")
+      expect(tokens[0][0].value).toBe("3.141_592");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[0][1].value).toBe("j");
+      expect(tokens[0][1].scopes).toEqual(["source.python","constant.numeric.float.python","storage.type.imaginary.number.python"]);
+      expect(tokens[1][0].value).toBe("10_000.");
+      expect(tokens[1][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[1][1].value).toBe("j");
+      expect(tokens[1][1].scopes).toEqual(["source.python","constant.numeric.float.python","storage.type.imaginary.number.python"]);
+      expect(tokens[2][0].value).toBe("10_000");
+      expect(tokens[2][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[2][1].value).toBe("j");
+      expect(tokens[2][1].scopes).toEqual(["source.python","constant.numeric.dec.python","storage.type.imaginary.number.python"]);
+      expect(tokens[3][0].value).toBe(".001_123");
+      expect(tokens[3][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[3][1].value).toBe("j");
+      expect(tokens[3][1].scopes).toEqual(["source.python","constant.numeric.float.python","storage.type.imaginary.number.python"]);
+      expect(tokens[4][0].value).toBe("1e10_000");
+      expect(tokens[4][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[4][1].value).toBe("j");
+      expect(tokens[4][1].scopes).toEqual(["source.python","constant.numeric.float.python","storage.type.imaginary.number.python"]);
+      expect(tokens[5][0].value).toBe("3.141_592e-10_000");
+      expect(tokens[5][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[5][1].value).toBe("j");
+      expect(tokens[5][1].scopes).toEqual(["source.python","constant.numeric.float.python","storage.type.imaginary.number.python"]);
+    });
+
+  it("test/numbers/dec.py", 
+    function() {
+      tokens = grammar.tokenizeLines("123\n000\n123_456\n1_2_3_4_5_6")
+      expect(tokens[0][0].value).toBe("123");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][0].value).toBe("000");
+      expect(tokens[1][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[2][0].value).toBe("123_456");
+      expect(tokens[2][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[3][0].value).toBe("1_2_3_4_5_6");
+      expect(tokens[3][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/numbers/floats1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("123.456\n0.456\n000.0001\n.01234\n123e5\n123e-5\n000123e-005\n123.456e+5\n0.456e-5")
+      expect(tokens[0][0].value).toBe("123.456");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[1][0].value).toBe("0.456");
+      expect(tokens[1][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[2][0].value).toBe("000.0001");
+      expect(tokens[2][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[3][0].value).toBe(".01234");
+      expect(tokens[3][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[4][0].value).toBe("123e5");
+      expect(tokens[4][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[5][0].value).toBe("123e-5");
+      expect(tokens[5][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[6][0].value).toBe("000123e-005");
+      expect(tokens[6][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[7][0].value).toBe("123.456e+5");
+      expect(tokens[7][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[8][0].value).toBe("0.456e-5");
+      expect(tokens[8][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+    });
+
+  it("test/numbers/floats2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("1_234.567_890\n0.456_789\n000.000_1\n.012_34\n1_234e5_000\n1_234e-5_000\n000_123e-000_5\n1_234.567_8e+5_000\n0.456_78e-5_000")
+      expect(tokens[0][0].value).toBe("1_234.567_890");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[1][0].value).toBe("0.456_789");
+      expect(tokens[1][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[2][0].value).toBe("000.000_1");
+      expect(tokens[2][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[3][0].value).toBe(".012_34");
+      expect(tokens[3][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[4][0].value).toBe("1_234e5_000");
+      expect(tokens[4][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[5][0].value).toBe("1_234e-5_000");
+      expect(tokens[5][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[6][0].value).toBe("000_123e-000_5");
+      expect(tokens[6][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[7][0].value).toBe("1_234.567_8e+5_000");
+      expect(tokens[7][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+      expect(tokens[8][0].value).toBe("0.456_78e-5_000");
+      expect(tokens[8][0].scopes).toEqual(["source.python","constant.numeric.float.python"]);
+    });
+
+  it("test/numbers/invalid.py", 
+    function() {
+      tokens = grammar.tokenizeLines("0123\n0123l\n123f\n123d\n123A\n123__456\n123_")
+      expect(tokens[0][0].value).toBe("0");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][1].value).toBe("123");
+      expect(tokens[0][1].scopes).toEqual(["source.python","constant.numeric.dec.python","invalid.illegal.dec.python"]);
+      expect(tokens[1][0].value).toBe("0123l");
+      expect(tokens[1][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+      expect(tokens[2][0].value).toBe("123f");
+      expect(tokens[2][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+      expect(tokens[3][0].value).toBe("123d");
+      expect(tokens[3][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+      expect(tokens[4][0].value).toBe("123A");
+      expect(tokens[4][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+      expect(tokens[5][0].value).toBe("123__456");
+      expect(tokens[5][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+      expect(tokens[6][0].value).toBe("123_");
+      expect(tokens[6][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+    });
+
+  it("test/numbers/nondec.py", 
+    function() {
+      tokens = grammar.tokenizeLines("0o1234567\n0O1234567\n0o1_234_567\n0b0000\n0B0001\n0b_0011_1001\n0xabcdef01234567890\n0XFF12\n0xab_cd_ef_01_23_45_67_89_00\n\n0o\n0b\n0x\n0z\n\n0b02\n0x0z\n0o90")
+      expect(tokens[0][0].value).toBe("0o");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.numeric.oct.python","storage.type.number.python"]);
+      expect(tokens[0][1].value).toBe("1234567");
+      expect(tokens[0][1].scopes).toEqual(["source.python","constant.numeric.oct.python"]);
+      expect(tokens[1][0].value).toBe("0O");
+      expect(tokens[1][0].scopes).toEqual(["source.python","constant.numeric.oct.python","storage.type.number.python"]);
+      expect(tokens[1][1].value).toBe("1234567");
+      expect(tokens[1][1].scopes).toEqual(["source.python","constant.numeric.oct.python"]);
+      expect(tokens[2][0].value).toBe("0o");
+      expect(tokens[2][0].scopes).toEqual(["source.python","constant.numeric.oct.python","storage.type.number.python"]);
+      expect(tokens[2][1].value).toBe("1_234_567");
+      expect(tokens[2][1].scopes).toEqual(["source.python","constant.numeric.oct.python"]);
+      expect(tokens[3][0].value).toBe("0b");
+      expect(tokens[3][0].scopes).toEqual(["source.python","constant.numeric.bin.python","storage.type.number.python"]);
+      expect(tokens[3][1].value).toBe("0000");
+      expect(tokens[3][1].scopes).toEqual(["source.python","constant.numeric.bin.python"]);
+      expect(tokens[4][0].value).toBe("0B");
+      expect(tokens[4][0].scopes).toEqual(["source.python","constant.numeric.bin.python","storage.type.number.python"]);
+      expect(tokens[4][1].value).toBe("0001");
+      expect(tokens[4][1].scopes).toEqual(["source.python","constant.numeric.bin.python"]);
+      expect(tokens[5][0].value).toBe("0b");
+      expect(tokens[5][0].scopes).toEqual(["source.python","constant.numeric.bin.python","storage.type.number.python"]);
+      expect(tokens[5][1].value).toBe("_0011_1001");
+      expect(tokens[5][1].scopes).toEqual(["source.python","constant.numeric.bin.python"]);
+      expect(tokens[6][0].value).toBe("0x");
+      expect(tokens[6][0].scopes).toEqual(["source.python","constant.numeric.hex.python","storage.type.number.python"]);
+      expect(tokens[6][1].value).toBe("abcdef01234567890");
+      expect(tokens[6][1].scopes).toEqual(["source.python","constant.numeric.hex.python"]);
+      expect(tokens[7][0].value).toBe("0X");
+      expect(tokens[7][0].scopes).toEqual(["source.python","constant.numeric.hex.python","storage.type.number.python"]);
+      expect(tokens[7][1].value).toBe("FF12");
+      expect(tokens[7][1].scopes).toEqual(["source.python","constant.numeric.hex.python"]);
+      expect(tokens[8][0].value).toBe("0x");
+      expect(tokens[8][0].scopes).toEqual(["source.python","constant.numeric.hex.python","storage.type.number.python"]);
+      expect(tokens[8][1].value).toBe("ab_cd_ef_01_23_45_67_89_00");
+      expect(tokens[8][1].scopes).toEqual(["source.python","constant.numeric.hex.python"]);
+      expect(tokens[9][0].value).toBe("");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][0].value).toBe("0o");
+      expect(tokens[10][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+      expect(tokens[11][0].value).toBe("0b");
+      expect(tokens[11][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+      expect(tokens[12][0].value).toBe("0x");
+      expect(tokens[12][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+      expect(tokens[13][0].value).toBe("0z");
+      expect(tokens[13][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+      expect(tokens[14][0].value).toBe("");
+      expect(tokens[14][0].scopes).toEqual(["source.python"]);
+      expect(tokens[15][0].value).toBe("0b02");
+      expect(tokens[15][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+      expect(tokens[16][0].value).toBe("0x0z");
+      expect(tokens[16][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+      expect(tokens[17][0].value).toBe("0o90");
+      expect(tokens[17][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+    });
+
+  it("test/numbers/python2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("123l\n123L\n1_234l")
+      expect(tokens[0][0].value).toBe("123");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.numeric.bin.python"]);
+      expect(tokens[0][1].value).toBe("l");
+      expect(tokens[0][1].scopes).toEqual(["source.python","constant.numeric.bin.python","storage.type.number.python"]);
+      expect(tokens[1][0].value).toBe("123");
+      expect(tokens[1][0].scopes).toEqual(["source.python","constant.numeric.bin.python"]);
+      expect(tokens[1][1].value).toBe("L");
+      expect(tokens[1][1].scopes).toEqual(["source.python","constant.numeric.bin.python","storage.type.number.python"]);
+      expect(tokens[2][0].value).toBe("1_234l");
+      expect(tokens[2][0].scopes).toEqual(["source.python","invalid.illegal.name.python"]);
+    });
+
+  it("test/regexp/comments1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r'''foo[abc] # comment'''")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'''");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("foo");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[0][7].value).toBe("[");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[0][8].value).toBe("a");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][9].value).toBe("b");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][10].value).toBe("c");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][11].value).toBe("]");
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[0][12].value).toBe(" ");
+      expect(tokens[0][12].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[0][13].value).toBe("#");
+      expect(tokens[0][13].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][14].value).toBe(" comment");
+      expect(tokens[0][14].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[0][15].value).toBe("'''");
+      expect(tokens[0][15].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/fregexp1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = fr'[a-z]'\na = Fr'[a-z]'\na = rf'[a-z]'\na = rF'[a-z]'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("fr");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("[");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[0][7].value).toBe("a");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][8].value).toBe("-");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][9].value).toBe("z");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][10].value).toBe("]");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[0][11].value).toBe("'");
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("Fr");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("[");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[1][7].value).toBe("a");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[1][8].value).toBe("-");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[1][9].value).toBe("z");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[1][10].value).toBe("]");
+      expect(tokens[1][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[1][11].value).toBe("'");
+      expect(tokens[1][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("rf");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("[");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[2][7].value).toBe("a");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[2][8].value).toBe("-");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[2][9].value).toBe("z");
+      expect(tokens[2][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[2][10].value).toBe("]");
+      expect(tokens[2][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[2][11].value).toBe("'");
+      expect(tokens[2][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("rF");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[3][5].value).toBe("'");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][6].value).toBe("[");
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[3][7].value).toBe("a");
+      expect(tokens[3][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[3][8].value).toBe("-");
+      expect(tokens[3][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[3][9].value).toBe("z");
+      expect(tokens[3][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[3][10].value).toBe("]");
+      expect(tokens[3][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[3][11].value).toBe("'");
+      expect(tokens[3][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/fregexp2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("rf'fo{{2}}'\nrf\"fo{{2}}\"\nrf'''fo{{2}}'''\nrf\"\"\"fo{{2}}\"\"\"")
+      expect(tokens[0][0].value).toBe("rf");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("fo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{{2}}");
+      expect(tokens[0][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("rf");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[1][1].value).toBe("\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("fo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][3].value).toBe("{{2}}");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[1][4].value).toBe("\"");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("rf");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[2][1].value).toBe("'''");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("fo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][3].value).toBe("{{2}}");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[2][4].value).toBe("'''");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("rf");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[3][1].value).toBe("\"\"\"");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe("fo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[3][3].value).toBe("{{2}}");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[3][4].value).toBe("\"\"\"");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/fregexp3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("rf'fo{2}'\nrf\"fo{2}\"\nrf'''fo{2}'''\nrf\"\"\"fo{2}\"\"\"")
+      expect(tokens[0][0].value).toBe("rf");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("fo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{2}");
+      expect(tokens[0][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("rf");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[1][1].value).toBe("\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("fo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][3].value).toBe("{2}");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][4].value).toBe("\"");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("rf");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[2][1].value).toBe("'''");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("fo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][3].value).toBe("{2}");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[2][4].value).toBe("'''");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("rf");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[3][1].value).toBe("\"\"\"");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe("fo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[3][3].value).toBe("{2}");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
+      expect(tokens[3][4].value).toBe("\"\"\"");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/fregexp4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = rf'fo{{2}}'\na = r'fo{{2}}'\na = r'fo{2}'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("rf");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("fo");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][7].value).toBe("{{2}}");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[0][8].value).toBe("'");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("r");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("fo{");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[1][7].value).toBe("{2}");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[1][8].value).toBe("}");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[1][9].value).toBe("'");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("r");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("fo");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[2][7].value).toBe("{2}");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[2][8].value).toBe("'");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/fregexp5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = rf'{{foo}}'\na = r'\\{foo\\}'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("rf");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("{{");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
+      expect(tokens[0][7].value).toBe("foo");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][8].value).toBe("}}");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
+      expect(tokens[0][9].value).toBe("'");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("r");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("\\{");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","constant.character.escape.regexp"]);
+      expect(tokens[1][7].value).toBe("foo");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[1][8].value).toBe("\\}");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","constant.character.escape.regexp"]);
+      expect(tokens[1][9].value).toBe("'");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/fregexp6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = rf'fo{{{2}}}'\na = rf'fo{{{bar}}}'\na = rf'fo{{2}}'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("rf");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("fo");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][7].value).toBe("{{");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
+      expect(tokens[0][8].value).toBe("{2}");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][9].value).toBe("}}");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
+      expect(tokens[0][10].value).toBe("'");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("rf");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("fo");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][7].value).toBe("{{");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
+      expect(tokens[1][8].value).toBe("{bar}");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[1][9].value).toBe("}}");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
+      expect(tokens[1][10].value).toBe("'");
+      expect(tokens[1][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("rf");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("fo");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][7].value).toBe("{{2}}");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[2][8].value).toBe("'");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/python1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r'[a-z]'\na = R'[a-z]'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("[");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[0][7].value).toBe("a");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][8].value).toBe("-");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][9].value).toBe("z");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[0][10].value).toBe("]");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[0][11].value).toBe("'");
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("R");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.raw.single.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("[a-z]");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[1][7].value).toBe("'");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/python10.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r'(<\\' for\na = r\"(<\\\" for\na = r'[<\\' for\na = r\"[<\\\" for\na = r'(?=\\' for\na = r\"(?=\\\" for\na = r'(?P<a>\\' for\na = r\"(?P<a>\\\" for\na = r'(?<!a\\' for\na = r\"(?<!a\\\" for\nreturn some")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("(");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[0][7].value).toBe("<");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[0][8].value).toBe("\\'");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","constant.character.escape.regexp"]);
+      expect(tokens[0][9].value).toBe(" for");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[0][10].value).toBe("");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("r");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("\"");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("(");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[1][7].value).toBe("<");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[1][8].value).toBe("\\\"");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","constant.character.escape.regexp"]);
+      expect(tokens[1][9].value).toBe(" for");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[1][10].value).toBe("");
+      expect(tokens[1][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("r");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("[");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[2][7].value).toBe("<");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[2][8].value).toBe("\\'");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[2][9].value).toBe(" ");
+      expect(tokens[2][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[2][10].value).toBe("f");
+      expect(tokens[2][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[2][11].value).toBe("o");
+      expect(tokens[2][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[2][12].value).toBe("r");
+      expect(tokens[2][12].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[2][13].value).toBe("");
+      expect(tokens[2][13].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("r");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[3][5].value).toBe("\"");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][6].value).toBe("[");
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[3][7].value).toBe("<");
+      expect(tokens[3][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[3][8].value).toBe("\\\"");
+      expect(tokens[3][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[3][9].value).toBe(" ");
+      expect(tokens[3][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[3][10].value).toBe("f");
+      expect(tokens[3][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[3][11].value).toBe("o");
+      expect(tokens[3][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[3][12].value).toBe("r");
+      expect(tokens[3][12].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[3][13].value).toBe("");
+      expect(tokens[3][13].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[4][0].value).toBe("a");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("=");
+      expect(tokens[4][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][3].value).toBe(" ");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe("r");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[4][5].value).toBe("'");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][6].value).toBe("(");
+      expect(tokens[4][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.lookahead.regexp","punctuation.parenthesis.lookahead.begin.regexp"]);
+      expect(tokens[4][7].value).toBe("?=");
+      expect(tokens[4][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.lookahead.regexp"]);
+      expect(tokens[4][8].value).toBe("\\'");
+      expect(tokens[4][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","constant.character.escape.regexp"]);
+      expect(tokens[4][9].value).toBe(" for");
+      expect(tokens[4][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[4][10].value).toBe("");
+      expect(tokens[4][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[5][0].value).toBe("a");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe(" ");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("=");
+      expect(tokens[5][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[5][3].value).toBe(" ");
+      expect(tokens[5][3].scopes).toEqual(["source.python"]);
+      expect(tokens[5][4].value).toBe("r");
+      expect(tokens[5][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[5][5].value).toBe("\"");
+      expect(tokens[5][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][6].value).toBe("(");
+      expect(tokens[5][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.lookahead.regexp","punctuation.parenthesis.lookahead.begin.regexp"]);
+      expect(tokens[5][7].value).toBe("?=");
+      expect(tokens[5][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.lookahead.regexp"]);
+      expect(tokens[5][8].value).toBe("\\\"");
+      expect(tokens[5][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","constant.character.escape.regexp"]);
+      expect(tokens[5][9].value).toBe(" for");
+      expect(tokens[5][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[5][10].value).toBe("");
+      expect(tokens[5][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[6][0].value).toBe("a");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].value).toBe("=");
+      expect(tokens[6][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[6][3].value).toBe(" ");
+      expect(tokens[6][3].scopes).toEqual(["source.python"]);
+      expect(tokens[6][4].value).toBe("r");
+      expect(tokens[6][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[6][5].value).toBe("'");
+      expect(tokens[6][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][6].value).toBe("(");
+      expect(tokens[6][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.named.regexp","punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[6][7].value).toBe("?P<a>");
+      expect(tokens[6][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.named.regexp","entity.name.tag.named.group.regexp"]);
+      expect(tokens[6][8].value).toBe("\\'");
+      expect(tokens[6][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.named.regexp","constant.character.escape.regexp"]);
+      expect(tokens[6][9].value).toBe(" for");
+      expect(tokens[6][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.named.regexp"]);
+      expect(tokens[6][10].value).toBe("");
+      expect(tokens[6][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[7][0].value).toBe("a");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe(" ");
+      expect(tokens[7][1].scopes).toEqual(["source.python"]);
+      expect(tokens[7][2].value).toBe("=");
+      expect(tokens[7][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[7][3].value).toBe(" ");
+      expect(tokens[7][3].scopes).toEqual(["source.python"]);
+      expect(tokens[7][4].value).toBe("r");
+      expect(tokens[7][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[7][5].value).toBe("\"");
+      expect(tokens[7][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][6].value).toBe("(");
+      expect(tokens[7][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.named.regexp","punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[7][7].value).toBe("?P<a>");
+      expect(tokens[7][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.named.regexp","entity.name.tag.named.group.regexp"]);
+      expect(tokens[7][8].value).toBe("\\\"");
+      expect(tokens[7][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.named.regexp","constant.character.escape.regexp"]);
+      expect(tokens[7][9].value).toBe(" for");
+      expect(tokens[7][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","meta.named.regexp"]);
+      expect(tokens[7][10].value).toBe("");
+      expect(tokens[7][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[8][0].value).toBe("a");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe(" ");
+      expect(tokens[8][1].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].value).toBe("=");
+      expect(tokens[8][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[8][3].value).toBe(" ");
+      expect(tokens[8][3].scopes).toEqual(["source.python"]);
+      expect(tokens[8][4].value).toBe("r");
+      expect(tokens[8][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[8][5].value).toBe("'");
+      expect(tokens[8][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[8][6].value).toBe("(");
+      expect(tokens[8][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.lookbehind.negative.regexp","punctuation.parenthesis.lookbehind.begin.regexp"]);
+      expect(tokens[8][7].value).toBe("?<!");
+      expect(tokens[8][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.lookbehind.negative.regexp"]);
+      expect(tokens[8][8].value).toBe("a");
+      expect(tokens[8][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[8][9].value).toBe("\\'");
+      expect(tokens[8][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","constant.character.escape.regexp"]);
+      expect(tokens[8][10].value).toBe(" for");
+      expect(tokens[8][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[8][11].value).toBe("");
+      expect(tokens[8][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[9][0].value).toBe("a");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].value).toBe(" ");
+      expect(tokens[9][1].scopes).toEqual(["source.python"]);
+      expect(tokens[9][2].value).toBe("=");
+      expect(tokens[9][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[9][3].value).toBe(" ");
+      expect(tokens[9][3].scopes).toEqual(["source.python"]);
+      expect(tokens[9][4].value).toBe("r");
+      expect(tokens[9][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[9][5].value).toBe("\"");
+      expect(tokens[9][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[9][6].value).toBe("(");
+      expect(tokens[9][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.lookbehind.negative.regexp","punctuation.parenthesis.lookbehind.begin.regexp"]);
+      expect(tokens[9][7].value).toBe("?<!");
+      expect(tokens[9][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.lookbehind.negative.regexp"]);
+      expect(tokens[9][8].value).toBe("a");
+      expect(tokens[9][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[9][9].value).toBe("\\\"");
+      expect(tokens[9][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","constant.character.escape.regexp"]);
+      expect(tokens[9][10].value).toBe(" for");
+      expect(tokens[9][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[9][11].value).toBe("");
+      expect(tokens[9][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[10][0].value).toBe("return");
+      expect(tokens[10][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[10][1].value).toBe(" ");
+      expect(tokens[10][1].scopes).toEqual(["source.python"]);
+      expect(tokens[10][2].value).toBe("some");
+      expect(tokens[10][2].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/regexp/python11.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r\"\"\"\n    (?x)        # multi-XXXline XXX regexp\n        foo     (?# comm TODOent TODO)\n        foo     # type: int\n        foo     (?# type: int)\n\"\"\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("\"\"\"");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[1][1].value).toBe("(?x)");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[1][2].value).toBe("        ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[1][3].value).toBe("#");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][4].value).toBe(" multi-XXXline ");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[1][5].value).toBe("XXX");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[1][6].value).toBe(" regexp");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[2][0].value).toBe("        foo     ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[2][1].value).toBe("(?#");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.regexp","punctuation.comment.begin.regexp"]);
+      expect(tokens[2][2].value).toBe(" comm TODOent ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.regexp"]);
+      expect(tokens[2][3].value).toBe("TODO");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.regexp","keyword.codetag.notation.python"]);
+      expect(tokens[2][4].value).toBe(")");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.regexp","punctuation.comment.end.regexp"]);
+      expect(tokens[3][0].value).toBe("        foo     ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][1].value).toBe("#");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][2].value).toBe(" type: int");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[4][0].value).toBe("        foo     ");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[4][1].value).toBe("(?#");
+      expect(tokens[4][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.regexp","punctuation.comment.begin.regexp"]);
+      expect(tokens[4][2].value).toBe(" type: int");
+      expect(tokens[4][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.regexp"]);
+      expect(tokens[4][3].value).toBe(")");
+      expect(tokens[4][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.regexp","punctuation.comment.end.regexp"]);
+      expect(tokens[5][0].value).toBe("\"\"\"");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/python2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r'\n    (?x)\n        foo\n'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("(");
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[1][2].value).toBe("?");
+      expect(tokens[1][2].scopes).toEqual(["source.python","invalid.illegal.operator.python"]);
+      expect(tokens[1][3].value).toBe("x");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[2][0].value).toBe("        ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("foo");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("'");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][1].value).toBe("");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","invalid.illegal.newline.python"]);
+    });
+
+  it("test/regexp/python3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r'''\n    (?x)\n        foo\n'''\na = br'''\n    (?x)\n        foo\n'''\na = rb'''\n    (?x)\n        foo\n'''\na = Br'''\n    (?x)\n        foo\n'''\na = rB'''\n    (?x)\n        foo\n'''")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'''");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[1][1].value).toBe("(?x)");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[2][0].value).toBe("        foo");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][0].value).toBe("'''");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("a");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("=");
+      expect(tokens[4][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][3].value).toBe(" ");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe("br");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[4][5].value).toBe("'''");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[5][1].value).toBe("(?x)");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[6][0].value).toBe("        foo");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[7][0].value).toBe("'''");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("a");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe(" ");
+      expect(tokens[8][1].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].value).toBe("=");
+      expect(tokens[8][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[8][3].value).toBe(" ");
+      expect(tokens[8][3].scopes).toEqual(["source.python"]);
+      expect(tokens[8][4].value).toBe("rb");
+      expect(tokens[8][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[8][5].value).toBe("'''");
+      expect(tokens[8][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[9][0].value).toBe("    ");
+      expect(tokens[9][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[9][1].value).toBe("(?x)");
+      expect(tokens[9][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[10][0].value).toBe("        foo");
+      expect(tokens[10][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[11][0].value).toBe("'''");
+      expect(tokens[11][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[12][0].value).toBe("a");
+      expect(tokens[12][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][1].value).toBe(" ");
+      expect(tokens[12][1].scopes).toEqual(["source.python"]);
+      expect(tokens[12][2].value).toBe("=");
+      expect(tokens[12][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[12][3].value).toBe(" ");
+      expect(tokens[12][3].scopes).toEqual(["source.python"]);
+      expect(tokens[12][4].value).toBe("Br");
+      expect(tokens[12][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[12][5].value).toBe("'''");
+      expect(tokens[12][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[13][0].value).toBe("    ");
+      expect(tokens[13][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[13][1].value).toBe("(?x)");
+      expect(tokens[13][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[14][0].value).toBe("        foo");
+      expect(tokens[14][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[15][0].value).toBe("'''");
+      expect(tokens[15][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[16][0].value).toBe("a");
+      expect(tokens[16][0].scopes).toEqual(["source.python"]);
+      expect(tokens[16][1].value).toBe(" ");
+      expect(tokens[16][1].scopes).toEqual(["source.python"]);
+      expect(tokens[16][2].value).toBe("=");
+      expect(tokens[16][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[16][3].value).toBe(" ");
+      expect(tokens[16][3].scopes).toEqual(["source.python"]);
+      expect(tokens[16][4].value).toBe("rB");
+      expect(tokens[16][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[16][5].value).toBe("'''");
+      expect(tokens[16][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[17][0].value).toBe("    ");
+      expect(tokens[17][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[17][1].value).toBe("(?x)");
+      expect(tokens[17][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[18][0].value).toBe("        foo");
+      expect(tokens[18][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[19][0].value).toBe("'''");
+      expect(tokens[19][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/python4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r\"\"\"\n    (?x)\n        foo\n\"\"\"\na = br\"\"\"\n    (?x)\n        foo\n\"\"\"\na = rb\"\"\"\n    (?x)\n        foo\n\"\"\"\na = Br\"\"\"\n    (?x)\n        foo\n\"\"\"\na = rB\"\"\"\n    (?x)\n        foo\n\"\"\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("\"\"\"");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[1][1].value).toBe("(?x)");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[2][0].value).toBe("        foo");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][0].value).toBe("\"\"\"");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("a");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("=");
+      expect(tokens[4][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][3].value).toBe(" ");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe("br");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[4][5].value).toBe("\"\"\"");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[5][1].value).toBe("(?x)");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[6][0].value).toBe("        foo");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[7][0].value).toBe("\"\"\"");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("a");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe(" ");
+      expect(tokens[8][1].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].value).toBe("=");
+      expect(tokens[8][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[8][3].value).toBe(" ");
+      expect(tokens[8][3].scopes).toEqual(["source.python"]);
+      expect(tokens[8][4].value).toBe("rb");
+      expect(tokens[8][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[8][5].value).toBe("\"\"\"");
+      expect(tokens[8][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[9][0].value).toBe("    ");
+      expect(tokens[9][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[9][1].value).toBe("(?x)");
+      expect(tokens[9][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[10][0].value).toBe("        foo");
+      expect(tokens[10][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[11][0].value).toBe("\"\"\"");
+      expect(tokens[11][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[12][0].value).toBe("a");
+      expect(tokens[12][0].scopes).toEqual(["source.python"]);
+      expect(tokens[12][1].value).toBe(" ");
+      expect(tokens[12][1].scopes).toEqual(["source.python"]);
+      expect(tokens[12][2].value).toBe("=");
+      expect(tokens[12][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[12][3].value).toBe(" ");
+      expect(tokens[12][3].scopes).toEqual(["source.python"]);
+      expect(tokens[12][4].value).toBe("Br");
+      expect(tokens[12][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[12][5].value).toBe("\"\"\"");
+      expect(tokens[12][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[13][0].value).toBe("    ");
+      expect(tokens[13][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[13][1].value).toBe("(?x)");
+      expect(tokens[13][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[14][0].value).toBe("        foo");
+      expect(tokens[14][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[15][0].value).toBe("\"\"\"");
+      expect(tokens[15][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[16][0].value).toBe("a");
+      expect(tokens[16][0].scopes).toEqual(["source.python"]);
+      expect(tokens[16][1].value).toBe(" ");
+      expect(tokens[16][1].scopes).toEqual(["source.python"]);
+      expect(tokens[16][2].value).toBe("=");
+      expect(tokens[16][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[16][3].value).toBe(" ");
+      expect(tokens[16][3].scopes).toEqual(["source.python"]);
+      expect(tokens[16][4].value).toBe("rB");
+      expect(tokens[16][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[16][5].value).toBe("\"\"\"");
+      expect(tokens[16][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[17][0].value).toBe("    ");
+      expect(tokens[17][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[17][1].value).toBe("(?x)");
+      expect(tokens[17][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[18][0].value).toBe("        foo");
+      expect(tokens[18][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[19][0].value).toBe("\"\"\"");
+      expect(tokens[19][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/python5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r'foo#not a comment'\na = r'''\n    (?x)        # multi-line regexp\n        foo     # comment\n'''\na = R'''\n    (?x)        # not a\n        foo     # comment\n'''")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("foo#not a comment");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("r");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("'''");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[2][1].value).toBe("(?x)");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[2][2].value).toBe("        ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[2][3].value).toBe("#");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][4].value).toBe(" multi-line regexp");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[3][0].value).toBe("        foo     ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][1].value).toBe("#");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][2].value).toBe(" comment");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[4][0].value).toBe("'''");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("a");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe(" ");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("=");
+      expect(tokens[5][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[5][3].value).toBe(" ");
+      expect(tokens[5][3].scopes).toEqual(["source.python"]);
+      expect(tokens[5][4].value).toBe("R");
+      expect(tokens[5][4].scopes).toEqual(["source.python","string.quoted.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[5][5].value).toBe("'''");
+      expect(tokens[5][5].scopes).toEqual(["source.python","string.quoted.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][0].value).toBe("    (?x)        # not a");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[7][0].value).toBe("        foo     # comment");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[8][0].value).toBe("'''");
+      expect(tokens[8][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/python6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r\"foo#not a comment\"\na = r\"\"\"\n    (?x)        # multi-line regexp\n        foo     # comment\n\"\"\"\na = R\"\"\"\n    (?x)        # not a\n        foo     # comment\n\"\"\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("\"");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("foo#not a comment");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[0][7].value).toBe("\"");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("r");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("\"\"\"");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[2][1].value).toBe("(?x)");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[2][2].value).toBe("        ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[2][3].value).toBe("#");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][4].value).toBe(" multi-line regexp");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[3][0].value).toBe("        foo     ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][1].value).toBe("#");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][2].value).toBe(" comment");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[4][0].value).toBe("\"\"\"");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("a");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe(" ");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("=");
+      expect(tokens[5][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[5][3].value).toBe(" ");
+      expect(tokens[5][3].scopes).toEqual(["source.python"]);
+      expect(tokens[5][4].value).toBe("R");
+      expect(tokens[5][4].scopes).toEqual(["source.python","string.quoted.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[5][5].value).toBe("\"\"\"");
+      expect(tokens[5][5].scopes).toEqual(["source.python","string.quoted.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][0].value).toBe("    (?x)        # not a");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[7][0].value).toBe("        foo     # comment");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[8][0].value).toBe("\"\"\"");
+      expect(tokens[8][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/regexp/python7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r'('\n1\n\na = r\"(?=\"\n1\n\na = r\"\"\"(?:\n\"\"\"\n1\n\na = r'''[\n'''\n1")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("(");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("1");
+      expect(tokens[1][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("r");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[3][5].value).toBe("\"");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][6].value).toBe("(");
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.lookahead.regexp","punctuation.parenthesis.lookahead.begin.regexp"]);
+      expect(tokens[3][7].value).toBe("?=");
+      expect(tokens[3][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.lookahead.regexp"]);
+      expect(tokens[3][8].value).toBe("\"");
+      expect(tokens[3][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("1");
+      expect(tokens[4][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[5][0].value).toBe("");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("a");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].value).toBe("=");
+      expect(tokens[6][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[6][3].value).toBe(" ");
+      expect(tokens[6][3].scopes).toEqual(["source.python"]);
+      expect(tokens[6][4].value).toBe("r");
+      expect(tokens[6][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[6][5].value).toBe("\"\"\"");
+      expect(tokens[6][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][6].value).toBe("(?:");
+      expect(tokens[6][6].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[7][0].value).toBe("\"\"\"");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][0].value).toBe("1");
+      expect(tokens[8][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[9][0].value).toBe("");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][0].value).toBe("a");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe(" ");
+      expect(tokens[10][1].scopes).toEqual(["source.python"]);
+      expect(tokens[10][2].value).toBe("=");
+      expect(tokens[10][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[10][3].value).toBe(" ");
+      expect(tokens[10][3].scopes).toEqual(["source.python"]);
+      expect(tokens[10][4].value).toBe("r");
+      expect(tokens[10][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[10][5].value).toBe("'''");
+      expect(tokens[10][5].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][6].value).toBe("[");
+      expect(tokens[10][6].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[11][0].value).toBe("'''");
+      expect(tokens[11][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[12][0].value).toBe("1");
+      expect(tokens[12][0].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/regexp/python8.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# And now something fun!\n\nCookiePattern = re.compile(r\"\"\"\n    (?x)                           # This is a verbose pattern\n    \\s*                            # Optional whitespace at start of cookie\n    (?P<key>                       # Start of group 'key'\n    [\"\"\" + _LegalKeyChars + r\"\"\"]+?   # Any word of at least one letter\n    )                              # End of group 'key'\n    (                              # Optional group: there may not be a value.\n    \\s*=\\s*                          # Equal Sign\n    (?P<val>                         # Start of group 'val'\n    \"(?:[^\\\\\"]|\\\\.)*\"                  # Any doublequoted string\n    |                                  # or\n    \\w{3},\\s[\\w\\d\\s-]{9,11}\\s[\\d:]{8}\\sGMT  # Special case for \"expires\" attr\n    |                                  # or\n    [\"\"\" + _LegalValueChars + r\"\"\"]*      # Any word or empty string\n    )                                # End of group 'val'\n    )?                             # End of optional value group\n    \\s*                            # Any number of spaces.\n    (\\s+|;|$)                      # Ending either at space, semicolon, or EOS.\n    \"\"\", re.ASCII)                 # May be removed if safe.")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" And now something fun!");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("CookiePattern");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("re");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][5].value).toBe(".");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("compile");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[2][7].value).toBe("(");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][8].value).toBe("r");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[2][9].value).toBe("\"\"\"");
+      expect(tokens[2][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][1].value).toBe("(?x)");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[3][2].value).toBe("                           ");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][3].value).toBe("#");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][4].value).toBe(" This is a verbose pattern");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[4][1].value).toBe("\\s");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
+      expect(tokens[4][2].value).toBe("*");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[4][3].value).toBe("                            ");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[4][4].value).toBe("#");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[4][5].value).toBe(" Optional whitespace at start of cookie");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[5][1].value).toBe("(");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[5][2].value).toBe("?P<key>");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","entity.name.tag.named.group.regexp"]);
+      expect(tokens[5][3].value).toBe("                       ");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[5][4].value).toBe("#");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[5][5].value).toBe(" Start of group 'key'");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[6][0].value).toBe("    ");
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[6][1].value).toBe("[");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[6][2].value).toBe("\"\"\"");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][3].value).toBe(" ");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[6][4].value).toBe("+");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[6][5].value).toBe(" ");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[6][6].value).toBe("_LegalKeyChars");
+      expect(tokens[6][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[6][7].value).toBe(" ");
+      expect(tokens[6][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[6][8].value).toBe("+");
+      expect(tokens[6][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[6][9].value).toBe(" ");
+      expect(tokens[6][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[6][10].value).toBe("r");
+      expect(tokens[6][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[6][11].value).toBe("\"\"\"");
+      expect(tokens[6][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][12].value).toBe("]");
+      expect(tokens[6][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[6][13].value).toBe("+?");
+      expect(tokens[6][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[6][14].value).toBe("   ");
+      expect(tokens[6][14].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[6][15].value).toBe("#");
+      expect(tokens[6][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[6][16].value).toBe(" Any word of at least one letter");
+      expect(tokens[6][16].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[7][0].value).toBe("    )                              ");
+      expect(tokens[7][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[7][1].value).toBe("#");
+      expect(tokens[7][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[7][2].value).toBe(" End of group 'key'");
+      expect(tokens[7][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[8][0].value).toBe("    ");
+      expect(tokens[8][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[8][1].value).toBe("(");
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[8][2].value).toBe("                              ");
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[8][3].value).toBe("#");
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[8][4].value).toBe(" Optional group: there may not be a value.");
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[9][0].value).toBe("    ");
+      expect(tokens[9][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[9][1].value).toBe("\\s");
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
+      expect(tokens[9][2].value).toBe("*");
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[9][3].value).toBe("=");
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[9][4].value).toBe("\\s");
+      expect(tokens[9][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
+      expect(tokens[9][5].value).toBe("*");
+      expect(tokens[9][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[9][6].value).toBe("                          ");
+      expect(tokens[9][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[9][7].value).toBe("#");
+      expect(tokens[9][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[9][8].value).toBe(" Equal Sign");
+      expect(tokens[9][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[10][0].value).toBe("    ");
+      expect(tokens[10][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[10][1].value).toBe("(");
+      expect(tokens[10][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[10][2].value).toBe("?P<val>");
+      expect(tokens[10][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","entity.name.tag.named.group.regexp"]);
+      expect(tokens[10][3].value).toBe("                         ");
+      expect(tokens[10][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[10][4].value).toBe("#");
+      expect(tokens[10][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[10][5].value).toBe(" Start of group 'val'");
+      expect(tokens[10][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[11][0].value).toBe("    \"");
+      expect(tokens[11][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[11][1].value).toBe("(?:");
+      expect(tokens[11][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[11][2].value).toBe("[");
+      expect(tokens[11][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[11][3].value).toBe("^");
+      expect(tokens[11][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","keyword.operator.negation.regexp"]);
+      expect(tokens[11][4].value).toBe("\\\\");
+      expect(tokens[11][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[11][5].value).toBe("\"");
+      expect(tokens[11][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[11][6].value).toBe("]");
+      expect(tokens[11][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[11][7].value).toBe("|");
+      expect(tokens[11][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.disjunction.regexp"]);
+      expect(tokens[11][8].value).toBe("\\\\");
+      expect(tokens[11][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","constant.character.escape.regexp"]);
+      expect(tokens[11][9].value).toBe(".");
+      expect(tokens[11][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.match.any.regexp"]);
+      expect(tokens[11][10].value).toBe(")");
+      expect(tokens[11][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[11][11].value).toBe("*");
+      expect(tokens[11][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
+      expect(tokens[11][12].value).toBe("\"                  ");
+      expect(tokens[11][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[11][13].value).toBe("#");
+      expect(tokens[11][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[11][14].value).toBe(" Any doublequoted string");
+      expect(tokens[11][14].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[12][0].value).toBe("    ");
+      expect(tokens[12][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[12][1].value).toBe("|");
+      expect(tokens[12][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.disjunction.regexp"]);
+      expect(tokens[12][2].value).toBe("                                  ");
+      expect(tokens[12][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[12][3].value).toBe("#");
+      expect(tokens[12][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[12][4].value).toBe(" or");
+      expect(tokens[12][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[13][0].value).toBe("    ");
+      expect(tokens[13][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[13][1].value).toBe("\\w");
+      expect(tokens[13][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][2].value).toBe("{3}");
+      expect(tokens[13][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
+      expect(tokens[13][3].value).toBe(",");
+      expect(tokens[13][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[13][4].value).toBe("\\s");
+      expect(tokens[13][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][5].value).toBe("[");
+      expect(tokens[13][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[13][6].value).toBe("\\w");
+      expect(tokens[13][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][7].value).toBe("\\d");
+      expect(tokens[13][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][8].value).toBe("\\s");
+      expect(tokens[13][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][9].value).toBe("-");
+      expect(tokens[13][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[13][10].value).toBe("]");
+      expect(tokens[13][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[13][11].value).toBe("{9,11}");
+      expect(tokens[13][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
+      expect(tokens[13][12].value).toBe("\\s");
+      expect(tokens[13][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][13].value).toBe("[");
+      expect(tokens[13][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[13][14].value).toBe("\\d");
+      expect(tokens[13][14].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][15].value).toBe(":");
+      expect(tokens[13][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[13][16].value).toBe("]");
+      expect(tokens[13][16].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[13][17].value).toBe("{8}");
+      expect(tokens[13][17].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
+      expect(tokens[13][18].value).toBe("\\s");
+      expect(tokens[13][18].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][19].value).toBe("GMT  ");
+      expect(tokens[13][19].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[13][20].value).toBe("#");
+      expect(tokens[13][20].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[13][21].value).toBe(" Special case for \"expires\" attr");
+      expect(tokens[13][21].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[14][0].value).toBe("    ");
+      expect(tokens[14][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[14][1].value).toBe("|");
+      expect(tokens[14][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.disjunction.regexp"]);
+      expect(tokens[14][2].value).toBe("                                  ");
+      expect(tokens[14][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[14][3].value).toBe("#");
+      expect(tokens[14][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[14][4].value).toBe(" or");
+      expect(tokens[14][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[15][0].value).toBe("    ");
+      expect(tokens[15][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[15][1].value).toBe("[");
+      expect(tokens[15][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[15][2].value).toBe("\"\"\"");
+      expect(tokens[15][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[15][3].value).toBe(" ");
+      expect(tokens[15][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[15][4].value).toBe("+");
+      expect(tokens[15][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[15][5].value).toBe(" ");
+      expect(tokens[15][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[15][6].value).toBe("_LegalValueChars");
+      expect(tokens[15][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[15][7].value).toBe(" ");
+      expect(tokens[15][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[15][8].value).toBe("+");
+      expect(tokens[15][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[15][9].value).toBe(" ");
+      expect(tokens[15][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[15][10].value).toBe("r");
+      expect(tokens[15][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[15][11].value).toBe("\"\"\"");
+      expect(tokens[15][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[15][12].value).toBe("]");
+      expect(tokens[15][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[15][13].value).toBe("*");
+      expect(tokens[15][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[15][14].value).toBe("      ");
+      expect(tokens[15][14].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[15][15].value).toBe("#");
+      expect(tokens[15][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[15][16].value).toBe(" Any word or empty string");
+      expect(tokens[15][16].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[16][0].value).toBe("    )                                ");
+      expect(tokens[16][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[16][1].value).toBe("#");
+      expect(tokens[16][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[16][2].value).toBe(" End of group 'val'");
+      expect(tokens[16][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[17][0].value).toBe("    )");
+      expect(tokens[17][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[17][1].value).toBe("?");
+      expect(tokens[17][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[17][2].value).toBe("                             ");
+      expect(tokens[17][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[17][3].value).toBe("#");
+      expect(tokens[17][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[17][4].value).toBe(" End of optional value group");
+      expect(tokens[17][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[18][0].value).toBe("    ");
+      expect(tokens[18][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[18][1].value).toBe("\\s");
+      expect(tokens[18][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
+      expect(tokens[18][2].value).toBe("*");
+      expect(tokens[18][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[18][3].value).toBe("                            ");
+      expect(tokens[18][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[18][4].value).toBe("#");
+      expect(tokens[18][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[18][5].value).toBe(" Any number of spaces.");
+      expect(tokens[18][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[19][0].value).toBe("    ");
+      expect(tokens[19][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[19][1].value).toBe("(");
+      expect(tokens[19][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[19][2].value).toBe("\\s");
+      expect(tokens[19][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
+      expect(tokens[19][3].value).toBe("+");
+      expect(tokens[19][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[19][4].value).toBe("|");
+      expect(tokens[19][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.disjunction.regexp"]);
+      expect(tokens[19][5].value).toBe(";");
+      expect(tokens[19][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[19][6].value).toBe("|");
+      expect(tokens[19][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.disjunction.regexp"]);
+      expect(tokens[19][7].value).toBe("$");
+      expect(tokens[19][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.match.end.regexp"]);
+      expect(tokens[19][8].value).toBe(")");
+      expect(tokens[19][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[19][9].value).toBe("                      ");
+      expect(tokens[19][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[19][10].value).toBe("#");
+      expect(tokens[19][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[19][11].value).toBe(" Ending either at space, semicolon, or EOS.");
+      expect(tokens[19][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[20][0].value).toBe("    ");
+      expect(tokens[20][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[20][1].value).toBe("\"\"\"");
+      expect(tokens[20][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[20][2].value).toBe(",");
+      expect(tokens[20][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[20][3].value).toBe(" ");
+      expect(tokens[20][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[20][4].value).toBe("re");
+      expect(tokens[20][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[20][5].value).toBe(".");
+      expect(tokens[20][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[20][6].value).toBe("ASCII");
+      expect(tokens[20][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.other.caps.python"]);
+      expect(tokens[20][7].value).toBe(")");
+      expect(tokens[20][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[20][8].value).toBe("                 ");
+      expect(tokens[20][8].scopes).toEqual(["source.python"]);
+      expect(tokens[20][9].value).toBe("#");
+      expect(tokens[20][9].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[20][10].value).toBe(" May be removed if safe.");
+      expect(tokens[20][10].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/regexp/python9.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r'foo[^]'\na = r'foo[]'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("foo");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[0][7].value).toBe("[^]");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[0][8].value).toBe("'");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("r");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("foo");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[1][7].value).toBe("[]");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[1][8].value).toBe("'");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/semicolon/semi1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a;\n;\na=1; b")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(";");
+      expect(tokens[0][1].scopes).toEqual(["source.python","invalid.deprecated.semicolon.python"]);
+      expect(tokens[1][0].value).toBe(";");
+      expect(tokens[1][0].scopes).toEqual(["source.python","invalid.deprecated.semicolon.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("=");
+      expect(tokens[2][1].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][2].value).toBe("1");
+      expect(tokens[2][2].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[2][3].value).toBe("; ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("b");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/statements/annotation1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("some_number: int           # variable without initial value\nsome_list: List[int] = []  # variable with initial value")
+      expect(tokens[0][0].value).toBe("some_number");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(":");
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[0][2].value).toBe(" ");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe("int");
+      expect(tokens[0][3].scopes).toEqual(["source.python","support.type.python"]);
+      expect(tokens[0][4].value).toBe("           ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("#");
+      expect(tokens[0][5].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][6].value).toBe(" variable without initial value");
+      expect(tokens[0][6].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("some_list");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(":");
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("List");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.item-access.python"]);
+      expect(tokens[1][4].value).toBe("[");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][5].value).toBe("int");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","support.type.python"]);
+      expect(tokens[1][6].value).toBe("]");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][7].value).toBe(" ");
+      expect(tokens[1][7].scopes).toEqual(["source.python"]);
+      expect(tokens[1][8].value).toBe("=");
+      expect(tokens[1][8].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][9].value).toBe(" ");
+      expect(tokens[1][9].scopes).toEqual(["source.python"]);
+      expect(tokens[1][10].value).toBe("[");
+      expect(tokens[1][10].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[1][11].value).toBe("]");
+      expect(tokens[1][11].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[1][12].value).toBe("  ");
+      expect(tokens[1][12].scopes).toEqual(["source.python"]);
+      expect(tokens[1][13].value).toBe("#");
+      expect(tokens[1][13].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][14].value).toBe(" variable with initial value");
+      expect(tokens[1][14].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/statements/for1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("for a, b, c in b:\n    pass\nelse:\n    1/0")
+      expect(tokens[0][0].value).toBe("for");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("a");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(",");
+      expect(tokens[0][3].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("b");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe(",");
+      expect(tokens[0][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("c");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("in");
+      expect(tokens[0][10].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[0][11].value).toBe(" ");
+      expect(tokens[0][11].scopes).toEqual(["source.python"]);
+      expect(tokens[0][12].value).toBe("b");
+      expect(tokens[0][12].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].value).toBe(":");
+      expect(tokens[0][13].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("pass");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][0].value).toBe("else");
+      expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][1].value).toBe(":");
+      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("1");
+      expect(tokens[3][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[3][2].value).toBe("/");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[3][3].value).toBe("0");
+      expect(tokens[3][3].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/statements/global1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("global a, b, c")
+      expect(tokens[0][0].value).toBe("global");
+      expect(tokens[0][0].scopes).toEqual(["source.python","storage.modifier.declaration.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("a");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(",");
+      expect(tokens[0][3].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("b");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe(",");
+      expect(tokens[0][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("c");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/statements/if1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("if (a if b else c):\n    1\nelif b or c and d:\n    2\nelse:\n    3")
+      expect(tokens[0][0].value).toBe("if");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("(");
+      expect(tokens[0][2].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[0][3].value).toBe("a");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("if");
+      expect(tokens[0][5].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe("b");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe("else");
+      expect(tokens[0][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe("c");
+      expect(tokens[0][11].scopes).toEqual(["source.python"]);
+      expect(tokens[0][12].value).toBe(")");
+      expect(tokens[0][12].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[0][13].value).toBe(":");
+      expect(tokens[0][13].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("1");
+      expect(tokens[1][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[2][0].value).toBe("elif");
+      expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("b");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("or");
+      expect(tokens[2][4].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("c");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][7].value).toBe(" ");
+      expect(tokens[2][7].scopes).toEqual(["source.python"]);
+      expect(tokens[2][8].value).toBe("and");
+      expect(tokens[2][8].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[2][9].value).toBe(" ");
+      expect(tokens[2][9].scopes).toEqual(["source.python"]);
+      expect(tokens[2][10].value).toBe("d");
+      expect(tokens[2][10].scopes).toEqual(["source.python"]);
+      expect(tokens[2][11].value).toBe(":");
+      expect(tokens[2][11].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("2");
+      expect(tokens[3][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[4][0].value).toBe("else");
+      expect(tokens[4][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][1].value).toBe(":");
+      expect(tokens[4][1].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("3");
+      expect(tokens[5][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/statements/import1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("from ...foo import bar as spam, baz\nimport time as ham, datetime")
+      expect(tokens[0][0].value).toBe("from");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][1].value).toBe(" ...");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("import");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("bar");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("as");
+      expect(tokens[0][8].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("spam");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe(",");
+      expect(tokens[0][11].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][12].value).toBe(" ");
+      expect(tokens[0][12].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].value).toBe("baz");
+      expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("import");
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("time");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("as");
+      expect(tokens[1][4].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("ham");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe(",");
+      expect(tokens[1][7].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[1][8].value).toBe(" ");
+      expect(tokens[1][8].scopes).toEqual(["source.python"]);
+      expect(tokens[1][9].value).toBe("datetime");
+      expect(tokens[1][9].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/statements/import2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("from .... import a\nfrom ... import b\nfrom .. import c")
+      expect(tokens[0][0].value).toBe("from");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][1].value).toBe(" .... ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("import");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("a");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("from");
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][1].value).toBe(" ... ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("import");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("b");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("from");
+      expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[2][1].value).toBe(" .. ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("import");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("c");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/statements/import3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("from....import a\nfrom...import b\nfrom..import c\nfrom.import d")
+      expect(tokens[0][0].value).toBe("from");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][1].value).toBe("....");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("import");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("a");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("from");
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][1].value).toBe("...");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("import");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("b");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("from");
+      expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[2][1].value).toBe("..");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("import");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("c");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("from");
+      expect(tokens[3][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[3][1].value).toBe(".");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("import");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("d");
+      expect(tokens[3][4].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/statements/import4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("from....foo import a\nfrom...foo import b\nfrom..foo import c\nfrom.foo import d")
+      expect(tokens[0][0].value).toBe("from");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][1].value).toBe("....");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("import");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("a");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("from");
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][1].value).toBe("...");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("foo");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("import");
+      expect(tokens[1][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("b");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("from");
+      expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[2][1].value).toBe("..");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("import");
+      expect(tokens[2][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("c");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("from");
+      expect(tokens[3][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[3][1].value).toBe(".");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("foo");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("import");
+      expect(tokens[3][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[3][5].value).toBe(" ");
+      expect(tokens[3][5].scopes).toEqual(["source.python"]);
+      expect(tokens[3][6].value).toBe("d");
+      expect(tokens[3][6].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/statements/import5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("from.foo import d\nfrom.import a\n\nfoo.import\n\nraise Exception from Foo\n\ndef bar():\n    yield from baz")
+      expect(tokens[0][0].value).toBe("from");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("import");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("d");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("from");
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][1].value).toBe(".");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("import");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("a");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("foo");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(".");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("import");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("raise");
+      expect(tokens[5][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[5][1].value).toBe(" ");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("Exception");
+      expect(tokens[5][2].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[5][3].value).toBe(" ");
+      expect(tokens[5][3].scopes).toEqual(["source.python"]);
+      expect(tokens[5][4].value).toBe("from");
+      expect(tokens[5][4].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[5][5].value).toBe(" ");
+      expect(tokens[5][5].scopes).toEqual(["source.python"]);
+      expect(tokens[5][6].value).toBe("Foo");
+      expect(tokens[5][6].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][0].value).toBe("def");
+      expect(tokens[7][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[7][1].value).toBe(" ");
+      expect(tokens[7][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[7][2].value).toBe("bar");
+      expect(tokens[7][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[7][3].value).toBe("(");
+      expect(tokens[7][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[7][4].value).toBe(")");
+      expect(tokens[7][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[7][5].value).toBe(":");
+      expect(tokens[7][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[8][0].value).toBe("    ");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe("yield from");
+      expect(tokens[8][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[8][2].value).toBe(" ");
+      expect(tokens[8][2].scopes).toEqual(["source.python"]);
+      expect(tokens[8][3].value).toBe("baz");
+      expect(tokens[8][3].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/statements/import6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("from __future__ import generator_stop")
+      expect(tokens[0][0].value).toBe("from");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("__future__");
+      expect(tokens[0][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("import");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("generator_stop");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/statements/nonlocal1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("nonlocal a, b, c")
+      expect(tokens[0][0].value).toBe("nonlocal");
+      expect(tokens[0][0].scopes).toEqual(["source.python","storage.modifier.declaration.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("a");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(",");
+      expect(tokens[0][3].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("b");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe(",");
+      expect(tokens[0][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("c");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+    });
+
+  it("test/statements/try1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("try:\n    1/0\nexcept AbcError as ex:\n    pass\nexcept (ZeroDivisionError, GhiError) as ex:\n    print(ex)\nelse:\n    1\nfinally:\n    2")
+      expect(tokens[0][0].value).toBe("try");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(":");
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("1");
+      expect(tokens[1][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][2].value).toBe("/");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[1][3].value).toBe("0");
+      expect(tokens[1][3].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[2][0].value).toBe("except");
+      expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("AbcError");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("as");
+      expect(tokens[2][4].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("ex");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][7].value).toBe(":");
+      expect(tokens[2][7].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("pass");
+      expect(tokens[3][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][0].value).toBe("except");
+      expect(tokens[4][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("(");
+      expect(tokens[4][2].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[4][3].value).toBe("ZeroDivisionError");
+      expect(tokens[4][3].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[4][4].value).toBe(",");
+      expect(tokens[4][4].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[4][5].value).toBe(" ");
+      expect(tokens[4][5].scopes).toEqual(["source.python"]);
+      expect(tokens[4][6].value).toBe("GhiError");
+      expect(tokens[4][6].scopes).toEqual(["source.python"]);
+      expect(tokens[4][7].value).toBe(")");
+      expect(tokens[4][7].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[4][8].value).toBe(" ");
+      expect(tokens[4][8].scopes).toEqual(["source.python"]);
+      expect(tokens[4][9].value).toBe("as");
+      expect(tokens[4][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][10].value).toBe(" ");
+      expect(tokens[4][10].scopes).toEqual(["source.python"]);
+      expect(tokens[4][11].value).toBe("ex");
+      expect(tokens[4][11].scopes).toEqual(["source.python"]);
+      expect(tokens[4][12].value).toBe(":");
+      expect(tokens[4][12].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("print");
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[5][2].value).toBe("(");
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[5][3].value).toBe("ex");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[5][4].value).toBe(")");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[6][0].value).toBe("else");
+      expect(tokens[6][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[6][1].value).toBe(":");
+      expect(tokens[6][1].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("1");
+      expect(tokens[7][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[8][0].value).toBe("finally");
+      expect(tokens[8][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[8][1].value).toBe(":");
+      expect(tokens[8][1].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[9][0].value).toBe("    ");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].value).toBe("2");
+      expect(tokens[9][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
+  it("test/statements/while1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("while 1:\n    pass")
+      expect(tokens[0][0].value).toBe("while");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("1");
+      expect(tokens[0][2].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("pass");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/statements/with1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("with a as b, c as d:\n    pass")
+      expect(tokens[0][0].value).toBe("with");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("a");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("as");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("b");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe(",");
+      expect(tokens[0][7].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe("c");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe("as");
+      expect(tokens[0][11].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][12].value).toBe(" ");
+      expect(tokens[0][12].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].value).toBe("d");
+      expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[0][14].value).toBe(":");
+      expect(tokens[0][14].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("pass");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/strings/bad1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = \"bad \\\\ string\nfoo \\' \\\" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005\"\ndef foo(a=1): pass")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("\"");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("bad ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][6].value).toBe("\\\\");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[0][7].value).toBe(" string");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][8].value).toBe("");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[1][0].value).toBe("foo");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("\\");
+      expect(tokens[1][2].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][3].value).toBe("' \\\" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005\"");
+      expect(tokens[1][3].scopes).toEqual(["source.python","invalid.illegal.line.continuation.python"]);
+      expect(tokens[2][0].value).toBe("def");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[2][2].value).toBe("foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[2][3].value).toBe("(");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[2][4].value).toBe("a");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[2][5].value).toBe("=");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[2][6].value).toBe("1");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[2][7].value).toBe(")");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[2][8].value).toBe(":");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[2][9].value).toBe(" ");
+      expect(tokens[2][9].scopes).toEqual(["source.python"]);
+      expect(tokens[2][10].value).toBe("pass");
+      expect(tokens[2][10].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/strings/bad2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = b\"bad \\\\ string\nfoo \\' \\\" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005\"\n\ndef foo(a=1): pass")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("b");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("\"");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("bad ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[0][7].value).toBe("\\\\");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.binary.single.python","constant.character.escape.python"]);
+      expect(tokens[0][8].value).toBe(" string");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[0][9].value).toBe("");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.binary.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[1][0].value).toBe("foo");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("\\");
+      expect(tokens[1][2].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][3].value).toBe("' \\\" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005\"");
+      expect(tokens[1][3].scopes).toEqual(["source.python","invalid.illegal.line.continuation.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("def");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[3][2].value).toBe("foo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[3][3].value).toBe("(");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[3][4].value).toBe("a");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[3][5].value).toBe("=");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[3][6].value).toBe("1");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[3][7].value).toBe(")");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[3][8].value).toBe(":");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[3][9].value).toBe(" ");
+      expect(tokens[3][9].scopes).toEqual(["source.python"]);
+      expect(tokens[3][10].value).toBe("pass");
+      expect(tokens[3][10].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/strings/bad3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = r\"bad string\nfoo \\' \\\" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005\"\n\ndef foo(a=1): pass # doesn't break!")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("r");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("\"");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("bad string");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[0][7].value).toBe("");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[1][0].value).toBe("foo");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("\\");
+      expect(tokens[1][2].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][3].value).toBe("' \\\" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005\"");
+      expect(tokens[1][3].scopes).toEqual(["source.python","invalid.illegal.line.continuation.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("def");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[3][2].value).toBe("foo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[3][3].value).toBe("(");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[3][4].value).toBe("a");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[3][5].value).toBe("=");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[3][6].value).toBe("1");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[3][7].value).toBe(")");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[3][8].value).toBe(":");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[3][9].value).toBe(" ");
+      expect(tokens[3][9].scopes).toEqual(["source.python"]);
+      expect(tokens[3][10].value).toBe("pass");
+      expect(tokens[3][10].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[3][11].value).toBe(" ");
+      expect(tokens[3][11].scopes).toEqual(["source.python"]);
+      expect(tokens[3][12].value).toBe("#");
+      expect(tokens[3][12].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][13].value).toBe(" doesn't break!");
+      expect(tokens[3][13].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/strings/bytes1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = b\"\"\"\nmultiline \"binary\" string \\\n\n    \\xf1 \\u1234aaaa \\U1234aaaa\n\n    \\N{BLACK SPADE SUIT}\n\"\"\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("b");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("\"\"\"");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][0].value).toBe("multiline \"binary\" string ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[1][1].value).toBe("\\");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","constant.language.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[3][1].value).toBe("\\xf1");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][2].value).toBe(" \\u1234aaaa \\U1234aaaa");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[5][0].value).toBe("    \\N{BLACK SPADE SUIT}");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[6][0].value).toBe("\"\"\"");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/bytes2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a[1] = b'''\nmultiline 'binary' string \\\n\n    \\xf1 \\u1234aaaa \\U1234aaaa\n\n    \\N{BLACK SPADE SUIT}\n'''")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.item-access.python"]);
+      expect(tokens[0][1].value).toBe("[");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][2].value).toBe("1");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][3].value).toBe("]");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("=");
+      expect(tokens[0][5].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe("b");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.binary.multi.python","storage.type.string.python"]);
+      expect(tokens[0][8].value).toBe("'''");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][0].value).toBe("multiline 'binary' string ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[1][1].value).toBe("\\");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","constant.language.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[3][1].value).toBe("\\xf1");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.binary.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][2].value).toBe(" \\u1234aaaa \\U1234aaaa");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[5][0].value).toBe("    \\N{BLACK SPADE SUIT}");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python"]);
+      expect(tokens[6][0].value).toBe("'''");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.binary.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/escaping1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = \"simple \\\\ string \\\nfoo \\' \\\" \\a \\b \\c \\f \\n \\r \\t \\v \\5 \\55 \\555 \\05 \\005\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("\"");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("simple ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][6].value).toBe("\\\\");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[0][7].value).toBe(" string ");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][8].value).toBe("\\");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.language.python"]);
+      expect(tokens[1][0].value).toBe("foo ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][1].value).toBe("\\'");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][3].value).toBe("\\\"");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][4].value).toBe(" ");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][5].value).toBe("\\a");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][7].value).toBe("\\b");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][8].value).toBe(" \\c ");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][9].value).toBe("\\f");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][10].value).toBe(" ");
+      expect(tokens[1][10].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][11].value).toBe("\\n");
+      expect(tokens[1][11].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][12].value).toBe(" ");
+      expect(tokens[1][12].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][13].value).toBe("\\r");
+      expect(tokens[1][13].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][14].value).toBe(" ");
+      expect(tokens[1][14].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][15].value).toBe("\\t");
+      expect(tokens[1][15].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][16].value).toBe(" ");
+      expect(tokens[1][16].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][17].value).toBe("\\v");
+      expect(tokens[1][17].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][18].value).toBe(" ");
+      expect(tokens[1][18].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][19].value).toBe("\\5");
+      expect(tokens[1][19].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][20].value).toBe(" ");
+      expect(tokens[1][20].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][21].value).toBe("\\55");
+      expect(tokens[1][21].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][22].value).toBe(" ");
+      expect(tokens[1][22].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][23].value).toBe("\\555");
+      expect(tokens[1][23].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][24].value).toBe(" ");
+      expect(tokens[1][24].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][25].value).toBe("\\05");
+      expect(tokens[1][25].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][26].value).toBe(" ");
+      expect(tokens[1][26].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][27].value).toBe("\\005");
+      expect(tokens[1][27].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][28].value).toBe("\"");
+      expect(tokens[1][28].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/escaping2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("replace = {'\"' : R'\\\"',\n           \"'\" : R'\\'',\n           '\\\\': R'\\\\'}")
+      expect(tokens[0][0].value).toBe("replace");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("{");
+      expect(tokens[0][4].scopes).toEqual(["source.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("\"");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe(":");
+      expect(tokens[0][9].scopes).toEqual(["source.python","punctuation.separator.dict.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe("R");
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.raw.single.python","storage.type.string.python"]);
+      expect(tokens[0][12].value).toBe("'");
+      expect(tokens[0][12].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][13].value).toBe("\\\"");
+      expect(tokens[0][13].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[0][14].value).toBe("'");
+      expect(tokens[0][14].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][15].value).toBe(",");
+      expect(tokens[0][15].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[1][0].value).toBe("           ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("'");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][3].value).toBe("\"");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][4].value).toBe(" ");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","punctuation.separator.dict.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe("R");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.raw.single.python","storage.type.string.python"]);
+      expect(tokens[1][8].value).toBe("'");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][9].value).toBe("\\'");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[1][10].value).toBe("'");
+      expect(tokens[1][10].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][11].value).toBe(",");
+      expect(tokens[1][11].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[2][0].value).toBe("           ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("'");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("\\\\");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[2][3].value).toBe("'");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][4].value).toBe(":");
+      expect(tokens[2][4].scopes).toEqual(["source.python","punctuation.separator.dict.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("R");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.raw.single.python","storage.type.string.python"]);
+      expect(tokens[2][7].value).toBe("'");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][8].value).toBe("\\\\");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[2][9].value).toBe("'");
+      expect(tokens[2][9].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][10].value).toBe("}");
+      expect(tokens[2][10].scopes).toEqual(["source.python","punctuation.definition.dict.end.python"]);
+    });
+
+  it("test/strings/format1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = \"{0[ ]:X>+10d}\"\na = \"{0[ ]!s:X>+10d}\"\na = \"{0[ ]:Xd>+10d}\" #invalid")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("\"");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("{0[ ]");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].value).toBe(":X>+10d");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[0][7].value).toBe("}");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][8].value).toBe("\"");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("\"");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][5].value).toBe("{0[ ]");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][6].value).toBe("!s");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[1][7].value).toBe(":X>+10d");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[1][8].value).toBe("}");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][9].value).toBe("\"");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("\"");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][5].value).toBe("{0[ ]");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][6].value).toBe(":");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[2][7].value).toBe("Xd>+10d");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][8].value).toBe("}");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][9].value).toBe("\"");
+      expect(tokens[2][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][10].value).toBe(" ");
+      expect(tokens[2][10].scopes).toEqual(["source.python"]);
+      expect(tokens[2][11].value).toBe("#");
+      expect(tokens[2][11].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][12].value).toBe("invalid");
+      expect(tokens[2][12].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/strings/format10.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = '''blah {foo-bar %d\n       blah {foo-bar %d}\n       blah {foo-bar %d //insane {}}\n       {}blah {foo-bar %d //insane {}}'''")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("'''");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("blah {foo-bar ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[0][6].value).toBe("%d");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][0].value).toBe("       blah ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[1][1].value).toBe("{foo-bar ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[1][2].value).toBe("%d");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][3].value).toBe("}");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[2][0].value).toBe("       blah {foo-bar ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[2][1].value).toBe("%d");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][2].value).toBe(" //insane {}}");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[3][0].value).toBe("       {}blah {foo-bar ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[3][1].value).toBe("%d");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][2].value).toBe(" //insane {}}");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[3][3].value).toBe("'''");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/format11.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = R'''\\fr{still_ok}ac{m_{j \\rightarrow i}(\\mathrm{good})}\n        {not_ok} %d\n'''")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("R");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'''");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("\\fr");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[0][7].value).toBe("{still_ok}");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.raw.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][8].value).toBe("ac");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[0][9].value).toBe("{m_{j \\rightarrow i}(\\mathrm{good})}");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[1][0].value).toBe("        {not_ok} ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[1][1].value).toBe("%d");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.raw.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][0].value).toBe("'''");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/format12.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = R'$\\frac{m_{j \\%srightarrow i}(\\mathrm{%sgood})}{\\su%m{m_{j \\rightarrow i}}}$'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("R");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.raw.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("$\\frac");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[0][7].value).toBe("{m_{j \\");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[0][8].value).toBe("%s");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.raw.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][9].value).toBe("rightarrow i}(\\mathrm{");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[0][10].value).toBe("%s");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.raw.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][11].value).toBe("good})}{\\su%m{m_{j \\rightarrow i}}}$");
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[0][12].value).toBe("'");
+      expect(tokens[0][12].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/format13.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = '''\\n\n{% for item in seq %}\n    \\n {{ item }} \\n \\N{BLACK SPADE SUIT}\n{% endfor %}\n'''")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("'''");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("\\n");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.escape.python"]);
+      expect(tokens[1][0].value).toBe("{% for item in seq %}");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[2][1].value).toBe("\\n");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.escape.python"]);
+      expect(tokens[2][2].value).toBe(" {{ item }} ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[2][3].value).toBe("\\n");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.escape.python"]);
+      expect(tokens[2][4].value).toBe(" ");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[2][5].value).toBe("\\N{BLACK SPADE SUIT}");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][0].value).toBe("{% endfor %}");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[4][0].value).toBe("'''");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/format14.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = R'''\\n\n{% for item in seq %}\n    \\n {{ item }} \\n \\N{BLACK SPADE SUIT}\n{% endfor %}\n'''")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("R");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'''");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("\\n");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[1][0].value).toBe("{% for item in seq %}");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[2][0].value).toBe("    \\n {{ item }} \\n \\N{BLACK SPADE SUIT}");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[3][0].value).toBe("{% endfor %}");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[4][0].value).toBe("'''");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/format15.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = '''\n{{ before detection }}\n{# jinja comment #}\n{{ after detection }}\n'''")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("'''");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][0].value).toBe("{{");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][1].value).toBe(" before detection ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[1][2].value).toBe("}}");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][0].value).toBe("{# jinja comment #}");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[3][0].value).toBe("{{ after detection }}");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[4][0].value).toBe("'''");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/format2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = \"normal {{ normal }} normal {10!r} normal {fo.__add__!s}\".format(fo=1)")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("\"");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("normal ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][6].value).toBe("{{");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe(" normal ");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][8].value).toBe("}}");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][9].value).toBe(" normal ");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][10].value).toBe("{10");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][11].value).toBe("!r");
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[0][12].value).toBe("}");
+      expect(tokens[0][12].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][13].value).toBe(" normal ");
+      expect(tokens[0][13].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][14].value).toBe("{fo.__add__");
+      expect(tokens[0][14].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][15].value).toBe("!s");
+      expect(tokens[0][15].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[0][16].value).toBe("}");
+      expect(tokens[0][16].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][17].value).toBe("\"");
+      expect(tokens[0][17].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][18].value).toBe(".");
+      expect(tokens[0][18].scopes).toEqual(["source.python"]);
+      expect(tokens[0][19].value).toBe("format");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][20].value).toBe("(");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][21].value).toBe("fo");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][22].value).toBe("=");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][23].value).toBe("1");
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][24].value).toBe(")");
+      expect(tokens[0][24].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/strings/format3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = '%i' % 42\na = \"%(language)s has %(number)03d quote types.\"\na = b\"%(language)s has %(number)03d quote types.\"\na = R\"%(language)s has %(number)03d quote types.\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("%i");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].value).toBe("'");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("%");
+      expect(tokens[0][8].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("42");
+      expect(tokens[0][10].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("\"");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][5].value).toBe("%(language)s");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][6].value).toBe(" has ");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][7].value).toBe("%(number)03d");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][8].value).toBe(" quote types.");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][9].value).toBe("\"");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("b");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[2][5].value).toBe("\"");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("%(language)s");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.binary.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][7].value).toBe(" has ");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[2][8].value).toBe("%(number)03d");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.binary.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][9].value).toBe(" quote types.");
+      expect(tokens[2][9].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[2][10].value).toBe("\"");
+      expect(tokens[2][10].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("R");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.raw.single.python","storage.type.string.python"]);
+      expect(tokens[3][5].value).toBe("\"");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][6].value).toBe("%(language)s");
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.quoted.raw.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][7].value).toBe(" has ");
+      expect(tokens[3][7].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[3][8].value).toBe("%(number)03d");
+      expect(tokens[3][8].scopes).toEqual(["source.python","string.quoted.raw.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][9].value).toBe(" quote types.");
+      expect(tokens[3][9].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[3][10].value).toBe("\"");
+      expect(tokens[3][10].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/format4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = 'qqq{:%Y-%m-%d %H:%M:%S}www'\na = 'qqq{0:{fill}{align}16}www'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("qqq");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][6].value).toBe("{");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe(":");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[0][8].value).toBe("%Y-%m-%d %H:%M:%S");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][9].value).toBe("}");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][10].value).toBe("www");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][11].value).toBe("'");
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("'");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][5].value).toBe("qqq");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][6].value).toBe("{0");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][7].value).toBe(":");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[1][8].value).toBe("{fill}");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][9].value).toBe("{align}");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][10].value).toBe("16");
+      expect(tokens[1][10].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][11].value).toBe("}");
+      expect(tokens[1][11].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][12].value).toBe("www");
+      expect(tokens[1][12].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][13].value).toBe("'");
+      expect(tokens[1][13].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/format5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = 'qqq{0:{width}{base}}www'\na = 'qqq{0:$20}www'\na = 'qqq{0}www'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("qqq");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][6].value).toBe("{0");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe(":");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[0][8].value).toBe("{width}");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][9].value).toBe("{base}");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][10].value).toBe("}");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][11].value).toBe("www");
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][12].value).toBe("'");
+      expect(tokens[0][12].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("'");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][5].value).toBe("qqq");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][6].value).toBe("{0");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][7].value).toBe(":");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[1][8].value).toBe("$20");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][9].value).toBe("}");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][10].value).toBe("www");
+      expect(tokens[1][10].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][11].value).toBe("'");
+      expect(tokens[1][11].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("'");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][5].value).toBe("qqq");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][6].value).toBe("{0}");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][7].value).toBe("www");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][8].value).toBe("'");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/format6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = 'qqqwww'\na = ' { '\na = 'qqq{0:{widt' + 'h}{base}}www'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("qqqwww");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][6].value).toBe("'");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("'");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][5].value).toBe(" { ");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][6].value).toBe("'");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("'");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][5].value).toBe("qqq{0:{widt");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][6].value).toBe("'");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][7].value).toBe(" ");
+      expect(tokens[2][7].scopes).toEqual(["source.python"]);
+      expect(tokens[2][8].value).toBe("+");
+      expect(tokens[2][8].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[2][9].value).toBe(" ");
+      expect(tokens[2][9].scopes).toEqual(["source.python"]);
+      expect(tokens[2][10].value).toBe("'");
+      expect(tokens[2][10].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][11].value).toBe("h}");
+      expect(tokens[2][11].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][12].value).toBe("{base}");
+      expect(tokens[2][12].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][13].value).toBe("}www");
+      expect(tokens[2][13].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][14].value).toBe("'");
+      expect(tokens[2][14].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/format7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# XXX we have to highlight '% o' here, as it is a valid python\n# format spec. Otherwise, it would be hard to spot an error in\n# the code below.\na = '12% of %s' % ('name',)")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[0][2].value).toBe("XXX");
+      expect(tokens[0][2].scopes).toEqual(["source.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[0][3].value).toBe(" we have to highlight '% o' here, as it is a valid python");
+      expect(tokens[0][3].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("#");
+      expect(tokens[1][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][1].value).toBe(" format spec. Otherwise, it would be hard to spot an error in");
+      expect(tokens[1][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[2][0].value).toBe("#");
+      expect(tokens[2][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][1].value).toBe(" the code below.");
+      expect(tokens[2][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("'");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][5].value).toBe("12");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[3][6].value).toBe("% o");
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][7].value).toBe("f ");
+      expect(tokens[3][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[3][8].value).toBe("%s");
+      expect(tokens[3][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][9].value).toBe("'");
+      expect(tokens[3][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][10].value).toBe(" ");
+      expect(tokens[3][10].scopes).toEqual(["source.python"]);
+      expect(tokens[3][11].value).toBe("%");
+      expect(tokens[3][11].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[3][12].value).toBe(" ");
+      expect(tokens[3][12].scopes).toEqual(["source.python"]);
+      expect(tokens[3][13].value).toBe("(");
+      expect(tokens[3][13].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[3][14].value).toBe("'");
+      expect(tokens[3][14].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][15].value).toBe("name");
+      expect(tokens[3][15].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[3][16].value).toBe("'");
+      expect(tokens[3][16].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][17].value).toBe(",");
+      expect(tokens[3][17].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[3][18].value).toBe(")");
+      expect(tokens[3][18].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+    });
+
+  it("test/strings/format8.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = R'$\\frac{m_{j \\rightarrow i}(\\mathrm{good})}{\\sum{m_{j \\rightarrow i}}}$'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("R");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.raw.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("$\\frac");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[0][7].value).toBe("{m_{j \\rightarrow i}(\\mathrm{good})}{\\sum{m_{j \\rightarrow i}}}$");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[0][8].value).toBe("'");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/format9.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = 'blah {foo-bar %d'\na = 'blah {foo-bar %d}'\na = 'blah {foo-bar %d //insane {}}'\na = '{}blah {foo-bar %d //insane {}}'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("blah {foo-bar ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][6].value).toBe("%d");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("'");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][5].value).toBe("blah ");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][6].value).toBe("{foo-bar ");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][7].value).toBe("%d");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][8].value).toBe("}");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][9].value).toBe("'");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("'");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][5].value).toBe("blah ");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][6].value).toBe("{foo-bar ");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][7].value).toBe("%d");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][8].value).toBe(" //insane {}}");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][9].value).toBe("'");
+      expect(tokens[2][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("'");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][5].value).toBe("{}");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][6].value).toBe("blah ");
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[3][7].value).toBe("{foo-bar ");
+      expect(tokens[3][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[3][8].value).toBe("%d");
+      expect(tokens[3][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][9].value).toBe(" //insane {}}");
+      expect(tokens[3][9].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[3][10].value).toBe("'");
+      expect(tokens[3][10].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/note1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = 'XXX FIXME NB TODO'\na = r'XXX FIXME NB TODO'\na = b'XXX FIXME NB TODO'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("XXX FIXME NB TODO");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][6].value).toBe("'");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("r");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("XXX FIXME NB TODO");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[1][7].value).toBe("'");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("b");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("XXX FIXME NB TODO");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[2][7].value).toBe("'");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/prefixes1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = 's t r'\na = u's t r'\na = b's t r'\na = r's t r'\na = br's t r'\na = rb's t r'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("s t r");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][6].value).toBe("'");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("u");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("s t r");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][7].value).toBe("'");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("b");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("s t r");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[2][7].value).toBe("'");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("r");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[3][5].value).toBe("'");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][6].value).toBe("s t r");
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[3][7].value).toBe("'");
+      expect(tokens[3][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("a");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("=");
+      expect(tokens[4][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][3].value).toBe(" ");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe("br");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[4][5].value).toBe("'");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][6].value).toBe("s t r");
+      expect(tokens[4][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[4][7].value).toBe("'");
+      expect(tokens[4][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("a");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe(" ");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("=");
+      expect(tokens[5][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[5][3].value).toBe(" ");
+      expect(tokens[5][3].scopes).toEqual(["source.python"]);
+      expect(tokens[5][4].value).toBe("rb");
+      expect(tokens[5][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[5][5].value).toBe("'");
+      expect(tokens[5][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][6].value).toBe("s t r");
+      expect(tokens[5][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[5][7].value).toBe("'");
+      expect(tokens[5][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/prefixes2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = U'S T R'\na = B'S T R'\na = R'S T R'\na = BR'S T R'\na = RB'S T R'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("U");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("S T R");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("B");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("S T R");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[1][7].value).toBe("'");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("R");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.raw.single.python","storage.type.string.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("S T R");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[2][7].value).toBe("'");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("BR");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","storage.type.string.python"]);
+      expect(tokens[3][5].value).toBe("'");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][6].value).toBe("S T R");
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python"]);
+      expect(tokens[3][7].value).toBe("'");
+      expect(tokens[3][7].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("a");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("=");
+      expect(tokens[4][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][3].value).toBe(" ");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe("RB");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","storage.type.string.python"]);
+      expect(tokens[4][5].value).toBe("'");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][6].value).toBe("S T R");
+      expect(tokens[4][6].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python"]);
+      expect(tokens[4][7].value).toBe("'");
+      expect(tokens[4][7].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/prefixes3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = Ur'S T R'\na = UR'S T R'\na = uB'S T R'\na = Ru'S T R'\na = RU'S T R'\na = bR'S T R'\na = Rb'S T R'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("Ur");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","invalid.deprecated.prefix.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("S T R");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("UR");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.raw.single.python","invalid.deprecated.prefix.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("S T R");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
+      expect(tokens[1][7].value).toBe("'");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("uB");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("S T R");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][7].value).toBe("'");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("R");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.single.python","invalid.illegal.prefix.python"]);
+      expect(tokens[3][5].value).toBe("u");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[3][6].value).toBe("'");
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][7].value).toBe("S T R");
+      expect(tokens[3][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[3][8].value).toBe("'");
+      expect(tokens[3][8].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("a");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("=");
+      expect(tokens[4][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][3].value).toBe(" ");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe("R");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.single.python","invalid.illegal.prefix.python"]);
+      expect(tokens[4][5].value).toBe("U");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.quoted.single.python","storage.type.string.python"]);
+      expect(tokens[4][6].value).toBe("'");
+      expect(tokens[4][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][7].value).toBe("S T R");
+      expect(tokens[4][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[4][8].value).toBe("'");
+      expect(tokens[4][8].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][0].value).toBe("a");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe(" ");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("=");
+      expect(tokens[5][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[5][3].value).toBe(" ");
+      expect(tokens[5][3].scopes).toEqual(["source.python"]);
+      expect(tokens[5][4].value).toBe("bR");
+      expect(tokens[5][4].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","storage.type.string.python"]);
+      expect(tokens[5][5].value).toBe("'");
+      expect(tokens[5][5].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][6].value).toBe("S T R");
+      expect(tokens[5][6].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python"]);
+      expect(tokens[5][7].value).toBe("'");
+      expect(tokens[5][7].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][0].value).toBe("a");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].value).toBe("=");
+      expect(tokens[6][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[6][3].value).toBe(" ");
+      expect(tokens[6][3].scopes).toEqual(["source.python"]);
+      expect(tokens[6][4].value).toBe("Rb");
+      expect(tokens[6][4].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","storage.type.string.python"]);
+      expect(tokens[6][5].value).toBe("'");
+      expect(tokens[6][5].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][6].value).toBe("S T R");
+      expect(tokens[6][6].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python"]);
+      expect(tokens[6][7].value).toBe("'");
+      expect(tokens[6][7].scopes).toEqual(["source.python","string.quoted.raw.binary.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/raw1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = R\"\"\"\nmultiline \"raw\" string \\\n\n    \\xf1 \\u1234aaaa \\U1234aaaa\n\n    \\N{BLACK SPADE SUIT}\n\"\"\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("R");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.raw.multi.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("\"\"\"");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.raw.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][0].value).toBe("multiline \"raw\" string ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[1][1].value).toBe("\\");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[3][0].value).toBe("    \\xf1 \\u1234aaaa \\U1234aaaa");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[5][0].value).toBe("    \\N");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[5][1].value).toBe("{BLACK SPADE SUIT}");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
+      expect(tokens[6][0].value).toBe("\"\"\"");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/strings/unicode1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = \"\"\"\nmultiline \"unicode\" string \\\n\n    \\xf1 \\u1234aaaa \\U1234aaaa\n\n    \\N{BLACK SPADE SUIT}\n\"\"\"")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("\"\"\"");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][0].value).toBe("multiline \"unicode\" string ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[1][1].value).toBe("\\");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.multi.python","constant.language.python"]);
+      expect(tokens[2][0].value).toBe("");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[3][1].value).toBe("\\xf1");
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[3][3].value).toBe("\\u1234");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.escape.python"]);
+      expect(tokens[3][4].value).toBe("aaaa ");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[3][5].value).toBe("\\U1234aaaa");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.escape.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
+      expect(tokens[5][1].value).toBe("\\N{BLACK SPADE SUIT}");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.escape.python"]);
+      expect(tokens[6][0].value).toBe("\"\"\"");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/unicode/unicode1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("class Üa(Êa):\n    'Œ\\nŃ'\n    @æaœ\n    def ŌÏŒĘ(self, Ú=1):\n        print('превед 你好')\n        return Ù\n    ÜBER = 1\n    你好 = lambda: 你好\n    def 你好(): pass")
+      expect(tokens[0][0].value).toBe("class");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.class.python"]);
+      expect(tokens[0][2].value).toBe("Üa");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.class.python","entity.name.type.class.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.begin.python"]);
+      expect(tokens[0][4].value).toBe("Êa");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][5].value).toBe(")");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.definition.inheritance.end.python"]);
+      expect(tokens[0][6].value).toBe(":");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","punctuation.section.class.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("'");
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("Œ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[1][3].value).toBe("\\n");
+      expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.docstring.single.python","constant.character.escape.python"]);
+      expect(tokens[1][4].value).toBe("Ń");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.decorator.python"]);
+      expect(tokens[2][1].value).toBe("@");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][2].value).toBe("æaœ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[3][1].value).toBe("def");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[3][3].value).toBe("ŌÏŒĘ");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[3][4].value).toBe("(");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[3][5].value).toBe("self");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python","variable.parameter.function.language.special.self.python"]);
+      expect(tokens[3][6].value).toBe(",");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[3][7].value).toBe(" ");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[3][8].value).toBe("Ú");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[3][9].value).toBe("=");
+      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.python"]);
+      expect(tokens[3][10].value).toBe("1");
+      expect(tokens[3][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","constant.numeric.dec.python"]);
+      expect(tokens[3][11].value).toBe(")");
+      expect(tokens[3][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[3][12].value).toBe(":");
+      expect(tokens[3][12].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[4][0].value).toBe("        ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("print");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[4][2].value).toBe("(");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[4][3].value).toBe("'");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][4].value).toBe("превед 你好");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[4][5].value).toBe("'");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][6].value).toBe(")");
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[5][0].value).toBe("        ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("return");
+      expect(tokens[5][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[5][2].value).toBe(" ");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][3].value).toBe("Ù");
+      expect(tokens[5][3].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("    ");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe("ÜBER");
+      expect(tokens[6][1].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[6][2].value).toBe(" ");
+      expect(tokens[6][2].scopes).toEqual(["source.python"]);
+      expect(tokens[6][3].value).toBe("=");
+      expect(tokens[6][3].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[6][4].value).toBe(" ");
+      expect(tokens[6][4].scopes).toEqual(["source.python"]);
+      expect(tokens[6][5].value).toBe("1");
+      expect(tokens[6][5].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("你好");
+      expect(tokens[7][1].scopes).toEqual(["source.python"]);
+      expect(tokens[7][2].value).toBe(" ");
+      expect(tokens[7][2].scopes).toEqual(["source.python"]);
+      expect(tokens[7][3].value).toBe("=");
+      expect(tokens[7][3].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[7][4].value).toBe(" ");
+      expect(tokens[7][4].scopes).toEqual(["source.python"]);
+      expect(tokens[7][5].value).toBe("lambda");
+      expect(tokens[7][5].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[7][6].value).toBe(":");
+      expect(tokens[7][6].scopes).toEqual(["source.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[7][7].value).toBe(" ");
+      expect(tokens[7][7].scopes).toEqual(["source.python"]);
+      expect(tokens[7][8].value).toBe("你好");
+      expect(tokens[7][8].scopes).toEqual(["source.python"]);
+      expect(tokens[8][0].value).toBe("    ");
+      expect(tokens[8][0].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[8][1].value).toBe("def");
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[8][2].value).toBe(" ");
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[8][3].value).toBe("你好");
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[8][4].value).toBe("(");
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[8][5].value).toBe(")");
+      expect(tokens[8][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[8][6].value).toBe(":");
+      expect(tokens[8][6].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[8][7].value).toBe(" ");
+      expect(tokens[8][7].scopes).toEqual(["source.python"]);
+      expect(tokens[8][8].value).toBe("pass");
+      expect(tokens[8][8].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+});
+

From 992be43c8ee14ce634c39f9f79549f5f465bcdfb Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Thu, 23 Feb 2017 18:06:25 -0500
Subject: [PATCH 10/65] atom-sync: Recognize *.kv, *.tac, *.Snakefile as Python
 files

---
 grammars/MagicPython.cson            | 3 +++
 grammars/MagicPython.tmLanguage      | 3 +++
 grammars/src/MagicPython.syntax.yaml | 2 +-
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 9d9c9185..02c4f9d3 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -15,6 +15,9 @@ fileTypes: [
   "gyp"
   "gypi"
   "wsgi"
+  "kv"
+  "Snakefile"
+  "tac"
 ]
 first_line_match: "^#![ \\t]*/.*\\bpython[\\d\\.]*\\b"
 firstLineMatch: "^#![ \\t]*/.*\\bpython[\\d\\.]*\\b"
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index ccbc54d3..46828a64 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -22,6 +22,9 @@
       <string>gyp</string>
       <string>gypi</string>
       <string>wsgi</string>
+      <string>kv</string>
+      <string>Snakefile</string>
+      <string>tac</string>
     </array>
     <key>first_line_match</key>
     <string>^#![ \t]*/.*\bpython[\d\.]*\b</string>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 5411bf30..bc26dded 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -4,7 +4,7 @@ scopeName: source.python
 # NOTE: remember to update package.json with VSCode file types.
 fileTypes: [py, py3, rpy, pyw, cpy, pyi,
             SConstruct, Sconstruct, sconstruct, SConscript,
-            gyp, gypi, wsgi]
+            gyp, gypi, wsgi, kv, Snakefile, tac]
 first_line_match: ^#![ \t]*/.*\bpython[\d\.]*\b
 firstLineMatch: ^#![ \t]*/.*\bpython[\d\.]*\b
 uuid: 742deb57-6e38-4192-bed6-410746efd85d

From 0bb4727293b15450ca6cf2cb068addcf02cc2c10 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 24 Feb 2017 12:13:01 -0500
Subject: [PATCH 11/65] Add python-console.cson and python-traceback.cson for
 Atom compat

---
 grammars/python-console.cson   | 50 ++++++++++++++++++++++++++
 grammars/python-traceback.cson | 66 ++++++++++++++++++++++++++++++++++
 test/atom-spec/console-spec.js | 27 ++++++++++++++
 test/atom-spec/tb-spec.js      | 46 ++++++++++++++++++++++++
 4 files changed, 189 insertions(+)
 create mode 100644 grammars/python-console.cson
 create mode 100644 grammars/python-traceback.cson
 create mode 100644 test/atom-spec/console-spec.js
 create mode 100644 test/atom-spec/tb-spec.js

diff --git a/grammars/python-console.cson b/grammars/python-console.cson
new file mode 100644
index 00000000..21600219
--- /dev/null
+++ b/grammars/python-console.cson
@@ -0,0 +1,50 @@
+# Copyright (c) 2014 GitHub Inc.
+
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+# --------------------------------------------------------------------
+
+# This package was derived from a TextMate bundle located at
+# https://github.com/textmate/python.tmbundle and distributed under the following
+# license, located in `README.mdown`:
+
+# Permission to copy, use, modify, sell and distribute this
+# software is granted. This software is provided "as is" without
+# express or implied warranty, and with no claim as to its
+# suitability for any purpose.
+
+'scopeName': 'text.python.console'
+'name': 'Python Console'
+'fileTypes': [
+  'doctest'
+  'pycon'
+]
+'patterns': [
+  {
+    'match': '^(>{3}|\\.{3}|In \\[\\d+\\]:) (.+)$'
+    'captures':
+      '1':
+        'name': 'punctuation.separator.prompt.python.console'
+      '2':
+        'patterns': [
+          'include': 'source.python'
+        ]
+  }
+]
diff --git a/grammars/python-traceback.cson b/grammars/python-traceback.cson
new file mode 100644
index 00000000..1121bbd2
--- /dev/null
+++ b/grammars/python-traceback.cson
@@ -0,0 +1,66 @@
+# Copyright (c) 2014 GitHub Inc.
+
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+# --------------------------------------------------------------------
+
+# This package was derived from a TextMate bundle located at
+# https://github.com/textmate/python.tmbundle and distributed under the following
+# license, located in `README.mdown`:
+
+# Permission to copy, use, modify, sell and distribute this
+# software is granted. This software is provided "as is" without
+# express or implied warranty, and with no claim as to its
+# suitability for any purpose.
+
+'scopeName': 'text.python.traceback'
+'name': 'Python Traceback'
+'fileTypes': [
+  'pytb'
+]
+'patterns': [
+  {
+    'match': '^  File ("[^"]+"), line (\\d+)(?:, in (.+))?$'
+    'captures': {
+      '1':
+        'name': 'string.python.traceback'
+      '2':
+        'name': 'constant.numeric.python.traceback'
+      '3':
+        'name': 'entity.name.function.python.traceback'
+    }
+  }
+  {
+    'match': '^    (.+)$'
+    'captures':
+      '1':
+        'patterns': [
+          'include': 'source.python'
+        ]
+  }
+  {
+    'match': '^([^\\s:]+):(?: (.+))?$'
+    'captures':
+      '1':
+        'name': 'entity.name.type.class.python.traceback'
+      '2':
+        'name': 'string.python.traceback'
+  }
+]
diff --git a/test/atom-spec/console-spec.js b/test/atom-spec/console-spec.js
new file mode 100644
index 00000000..39c13528
--- /dev/null
+++ b/test/atom-spec/console-spec.js
@@ -0,0 +1,27 @@
+describe("python-console tests", function() {
+  var grammar = null;
+
+  beforeEach(function() {
+    waitsForPromise(function() {
+      return atom.packages.activatePackage("MagicPython")
+    });
+    runs(function() {
+      grammar = atom.grammars.grammarForScopeName("text.python.console")
+    });
+  });
+
+  it("highlights >>>", function() {
+    tokens = grammar.tokenizeLines(">>> print")
+
+    expect(tokens[0][0].value).toBe(">>>");
+    expect(tokens[0][0].scopes).toEqual(
+      ['text.python.console', 'punctuation.separator.prompt.python.console']);
+
+    expect(tokens[0][1].value).toBe(" ");
+    expect(tokens[0][1].scopes).toEqual(['text.python.console']);
+
+    expect(tokens[0][2].value).toBe("print");
+    expect(tokens[0][2].scopes).toEqual(
+      ['text.python.console', 'support.function.builtin.python']);
+  });
+});
diff --git a/test/atom-spec/tb-spec.js b/test/atom-spec/tb-spec.js
new file mode 100644
index 00000000..bb53fed2
--- /dev/null
+++ b/test/atom-spec/tb-spec.js
@@ -0,0 +1,46 @@
+describe("python-traceback tests", function() {
+  var grammar = null;
+
+  beforeEach(function() {
+    waitsForPromise(function() {
+      return atom.packages.activatePackage("MagicPython")
+    });
+    runs(function() {
+      grammar = atom.grammars.grammarForScopeName("text.python.traceback")
+    });
+  });
+
+  it("highlights a traceback line", function() {
+    tokens = grammar.tokenizeLines(
+      '  File "t.py", line 1, in <module>\n' +
+      '    a = 1/0')
+
+    expect(tokens[0][0].value).toBe("  File ");
+    expect(tokens[0][0].scopes).toEqual(['text.python.traceback']);
+
+    expect(tokens[0][1].value).toBe('"t.py"');
+    expect(tokens[0][1].scopes).toEqual(
+      ['text.python.traceback', 'string.python.traceback']);
+
+    expect(tokens[0][2].value).toBe(", line ");
+    expect(tokens[0][2].scopes).toEqual(['text.python.traceback']);
+
+    expect(tokens[0][3].value).toBe("1");
+    expect(tokens[0][3].scopes).toEqual(
+      ['text.python.traceback', 'constant.numeric.python.traceback']);
+
+    expect(tokens[0][4].value).toBe(", in ");
+    expect(tokens[0][4].scopes).toEqual(['text.python.traceback']);
+
+    expect(tokens[0][5].value).toBe("<module>");
+    expect(tokens[0][5].scopes).toEqual(
+      ['text.python.traceback', 'entity.name.function.python.traceback']);
+
+    expect(tokens[1][1].value).toBe("a");
+    expect(tokens[1][1].scopes).toEqual(['text.python.traceback']);
+
+    expect(tokens[1][3].value).toBe("=");
+    expect(tokens[1][3].scopes).toEqual(
+      ['text.python.traceback', 'keyword.operator.assignment.python']);
+  });
+});

From b75b17bf8e3acd3be35b1cecc7eff9da0e734260 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 24 Feb 2017 12:25:13 -0500
Subject: [PATCH 12/65] Prepare 1.0.7 release

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index b525cf27..32215ea6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "MagicPython",
-  "version": "1.0.6",
+  "version": "1.0.7",
   "engines": {
     "atom": "*",
     "node": "*",

From ef3eb6135b958b80d3e5246a382c2c5459cc0e17 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Wed, 29 Mar 2017 19:38:20 -0400
Subject: [PATCH 13/65] Update constant highlighting rules.

We consider something to be a "special constant" if it starts with
"enough" (2 or more in this case) upper-case letters. Any leading
underscores are ignored for the purpose of this definition. Also any
number of underscores and digits are allowed in between the first 2
upper-case letters. To fully satisfy the requirement, the "leading" 2
upper-case letters must be followed by only upper-case letters or
digits until the first underscore.
---
 grammars/MagicPython.cson            |  7 +++++-
 grammars/MagicPython.tmLanguage      |  7 +++++-
 grammars/src/MagicPython.syntax.yaml |  7 +++++-
 test/atom-spec/python-spec.js        | 33 ++++++++++++++++++++++++++++
 test/expressions/const3.py           | 27 +++++++++++++++++++++++
 5 files changed, 78 insertions(+), 3 deletions(-)
 create mode 100644 test/expressions/const3.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 02c4f9d3..8a6e2278 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -437,8 +437,13 @@ repository:
     match: '''
       (?x)
         \\b
+          # we want to see "enough", meaning 2 or more upper-case
+          # letters in the beginning of the constant
+          #
+          # for more details refer to:
+          #   https://github.com/MagicStack/MagicPython/issues/42
           (
-            _* [[:upper:]]{2}
+            _* [[:upper:]] [_\\d]* [[:upper:]]
           )
           [[:upper:]\\d]* (_\\w*)?
         \\b
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 46828a64..e30ff7e5 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -662,8 +662,13 @@
         <key>match</key>
         <string>(?x)
   \b
+    # we want to see "enough", meaning 2 or more upper-case
+    # letters in the beginning of the constant
+    #
+    # for more details refer to:
+    #   https://github.com/MagicStack/MagicPython/issues/42
     (
-      _* [[:upper:]]{2}
+      _* [[:upper:]] [_\d]* [[:upper:]]
     )
     [[:upper:]\d]* (_\w*)?
   \b
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index bc26dded..6cbcf61d 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -448,8 +448,13 @@ repository:
     match: |
       (?x)
         \b
+          # we want to see "enough", meaning 2 or more upper-case
+          # letters in the beginning of the constant
+          #
+          # for more details refer to:
+          #   https://github.com/MagicStack/MagicPython/issues/42
           (
-            _* [[:upper:]]{2}
+            _* [[:upper:]] [_\d]* [[:upper:]]
           )
           [[:upper:]\d]* (_\w*)?
         \b
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 4fa5f031..4e139381 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -5025,6 +5025,39 @@ describe("Grammar Tests", function() {
       expect(tokens[1][12].scopes).toEqual(["source.python"]);
     });
 
+  it("test/expressions/const3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("T61STRING = 20\nT61_STRING\nT_STRING\n_T_S_T_R_I_N_G_\nA_CLASS\n\n# not enough upper-case letters in the beginning\n_T_s_TRING\nA_Class")
+      expect(tokens[0][0].value).toBe("T61STRING");
+      expect(tokens[0][0].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("20");
+      expect(tokens[0][4].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][0].value).toBe("T61_STRING");
+      expect(tokens[1][0].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[2][0].value).toBe("T_STRING");
+      expect(tokens[2][0].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[3][0].value).toBe("_T_S_T_R_I_N_G_");
+      expect(tokens[3][0].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[4][0].value).toBe("A_CLASS");
+      expect(tokens[4][0].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[5][0].value).toBe("");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("#");
+      expect(tokens[6][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[6][1].value).toBe(" not enough upper-case letters in the beginning");
+      expect(tokens[6][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[7][0].value).toBe("_T_s_TRING");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][0].value).toBe("A_Class");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+    });
+
   it("test/expressions/expr1.py", 
     function() {
       tokens = grammar.tokenizeLines("~a + b @ c ^ d // e % f & e and not g or h")
diff --git a/test/expressions/const3.py b/test/expressions/const3.py
new file mode 100644
index 00000000..252f8f3b
--- /dev/null
+++ b/test/expressions/const3.py
@@ -0,0 +1,27 @@
+T61STRING = 20
+T61_STRING
+T_STRING
+_T_S_T_R_I_N_G_
+A_CLASS
+
+# not enough upper-case letters in the beginning
+_T_s_TRING
+A_Class
+
+
+
+
+T61STRING     : constant.other.caps.python, source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+20            : constant.numeric.dec.python, source.python
+T61_STRING    : constant.other.caps.python, source.python
+T_STRING      : constant.other.caps.python, source.python
+_T_S_T_R_I_N_G_ : constant.other.caps.python, source.python
+A_CLASS       : constant.other.caps.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ not enough upper-case letters in the beginning : comment.line.number-sign.python, source.python
+_T_s_TRING    : source.python
+A_Class       : source.python

From 6a2dba3a72887ee9fe7e1f11788b3de4773ab4fe Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Wed, 29 Mar 2017 19:48:33 -0400
Subject: [PATCH 14/65] Prepare 1.0.8 release

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 32215ea6..5f473ced 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "MagicPython",
-  "version": "1.0.7",
+  "version": "1.0.8",
   "engines": {
     "atom": "*",
     "node": "*",

From 976e59dcb78cb577e79c8f2117216c06718337e0 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Wed, 29 Mar 2017 21:39:34 -0400
Subject: [PATCH 15/65] Drop `support.other.format.python` scope name.

We use this awkward scope name instead of perhaps more elegant
"support.other.format.python" because it appears that by default
it gives a better visual result in various systems (e.g. GitHub).
This is due to the fact that "storage.type..." is more likely to have
special highlighting in any given color scheme than "support.other..."
---
 grammars/MagicPython.cson              | 44 +++++++++++++-------------
 grammars/MagicPython.tmLanguage        | 44 +++++++++++++-------------
 grammars/src/MagicPython.syntax.yaml   | 12 +++++--
 grammars/src/pyfstring.inc.syntax.yaml | 28 ++++++++++------
 misc/scopes                            |  1 -
 test/atom-spec/python-spec.js          | 42 ++++++++++++------------
 test/fstrings/comment4.py              |  6 ++--
 test/fstrings/nested2.py               |  4 +--
 test/fstrings/nested3.py               |  4 +--
 test/fstrings/nested4.py               |  4 +--
 test/fstrings/simple1.py               |  4 +--
 test/fstrings/simple3.py               |  2 +-
 test/fstrings/simple4.py               |  2 +-
 test/fstrings/simple5.py               |  2 +-
 test/strings/format1.py                |  6 ++--
 test/strings/format4.py                |  4 +--
 test/strings/format5.py                |  4 +--
 17 files changed, 114 insertions(+), 99 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 8a6e2278..65b36733 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -950,7 +950,7 @@ repository:
           "2":
             name: "storage.type.format.python"
           "3":
-            name: "support.other.format.python"
+            name: "storage.type.format.python"
       }
       {
         name: "constant.character.format.placeholder.other.python"
@@ -968,7 +968,7 @@ repository:
           "2":
             name: "storage.type.format.python"
           "3":
-            name: "support.other.format.python"
+            name: "storage.type.format.python"
         patterns: [
           {
             match: '''
@@ -4620,7 +4620,7 @@ repository:
           "1":
             name: "storage.type.format.python"
           "2":
-            name: "support.other.format.python"
+            name: "storage.type.format.python"
       }
       {
         include: "#fstring-terminator-single-tail"
@@ -4633,7 +4633,7 @@ repository:
       "1":
         name: "storage.type.format.python"
       "2":
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
     patterns: [
       {
         include: "#fstring-illegal-single-brace"
@@ -4642,35 +4642,35 @@ repository:
         include: "#fstring-single-brace"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "([bcdeEfFgGnosxX%])(?=})"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "(\\.\\d+)"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "(,)"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "(\\d+)"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "(\\#)"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "([-+ ])"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "([<>=^])"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "(\\w)"
       }
     ]
@@ -4844,7 +4844,7 @@ repository:
           "1":
             name: "storage.type.format.python"
           "2":
-            name: "support.other.format.python"
+            name: "storage.type.format.python"
       }
       {
         include: "#fstring-terminator-multi-tail"
@@ -4857,7 +4857,7 @@ repository:
       "1":
         name: "storage.type.format.python"
       "2":
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
     patterns: [
       {
         include: "#fstring-illegal-multi-brace"
@@ -4866,35 +4866,35 @@ repository:
         include: "#fstring-multi-brace"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "([bcdeEfFgGnosxX%])(?=})"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "(\\.\\d+)"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "(,)"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "(\\d+)"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "(\\#)"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "([-+ ])"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "([<>=^])"
       }
       {
-        name: "support.other.format.python"
+        name: "storage.type.format.python"
         match: "(\\w)"
       }
     ]
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index e30ff7e5..784b4894 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -1454,7 +1454,7 @@
               <key>3</key>
               <dict>
                 <key>name</key>
-                <string>support.other.format.python</string>
+                <string>storage.type.format.python</string>
               </dict>
             </dict>
           </dict>
@@ -1481,7 +1481,7 @@
               <key>3</key>
               <dict>
                 <key>name</key>
-                <string>support.other.format.python</string>
+                <string>storage.type.format.python</string>
               </dict>
             </dict>
             <key>patterns</key>
@@ -8083,7 +8083,7 @@ indirectly through syntactic constructs
               <key>2</key>
               <dict>
                 <key>name</key>
-                <string>support.other.format.python</string>
+                <string>storage.type.format.python</string>
               </dict>
             </dict>
           </dict>
@@ -8109,7 +8109,7 @@ indirectly through syntactic constructs
           <key>2</key>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
           </dict>
         </dict>
         <key>patterns</key>
@@ -8124,49 +8124,49 @@ indirectly through syntactic constructs
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>([bcdeEfFgGnosxX%])(?=})</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>(\.\d+)</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>(,)</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>(\d+)</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>(\#)</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>([-+ ])</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>([&lt;&gt;=^])</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>(\w)</string>
           </dict>
@@ -8455,7 +8455,7 @@ indirectly through syntactic constructs
               <key>2</key>
               <dict>
                 <key>name</key>
-                <string>support.other.format.python</string>
+                <string>storage.type.format.python</string>
               </dict>
             </dict>
           </dict>
@@ -8481,7 +8481,7 @@ indirectly through syntactic constructs
           <key>2</key>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
           </dict>
         </dict>
         <key>patterns</key>
@@ -8496,49 +8496,49 @@ indirectly through syntactic constructs
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>([bcdeEfFgGnosxX%])(?=})</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>(\.\d+)</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>(,)</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>(\d+)</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>(\#)</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>([-+ ])</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>([&lt;&gt;=^])</string>
           </dict>
           <dict>
             <key>name</key>
-            <string>support.other.format.python</string>
+            <string>storage.type.format.python</string>
             <key>match</key>
             <string>(\w)</string>
           </dict>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 6cbcf61d..b43b8f84 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -793,8 +793,16 @@ repository:
                 })
             )
         captures:
+          # We use this awkward scope name instead of perhaps more
+          # elegant "support.other.format.python" because it appears
+          # that by default it gives a better visual result in various
+          # systems (e.g. GitHub). This is due to the fact that
+          # "storage.type..." is more likely to have special
+          # highlighting in any given color scheme than
+          # "support.other..."
+          #
           '2': {name: storage.type.format.python}
-          '3': {name: support.other.format.python}
+          '3': {name: storage.type.format.python}
       - name: constant.character.format.placeholder.other.python
         begin: |
           (?x)
@@ -806,7 +814,7 @@ repository:
         end: \}
         beginCaptures:
           '2': {name: storage.type.format.python}
-          '3': {name: support.other.format.python}
+          '3': {name: storage.type.format.python}
         patterns:
           - match: |
               (?x) \{ [^'"}\n]*? \} (?=.*?\})
diff --git a/grammars/src/pyfstring.inc.syntax.yaml b/grammars/src/pyfstring.inc.syntax.yaml
index 8a0a31c2..4daed8b4 100644
--- a/grammars/src/pyfstring.inc.syntax.yaml
+++ b/grammars/src/pyfstring.inc.syntax.yaml
@@ -135,8 +135,16 @@ repository:
               ( : \w? [<>=^]? [-+ ]? \#?
                 \d* ,? (\.\d+)? [bcdeEfFgGnosxX%]? )(?=})
         captures:
+          # We use this awkward scope name instead of perhaps more
+          # elegant "support.other.format.python" because it appears
+          # that by default it gives a better visual result in various
+          # systems (e.g. GitHub). This is due to the fact that
+          # "storage.type..." is more likely to have special
+          # highlighting in any given color scheme than
+          # "support.other..."
+          #
           '1': {name: storage.type.format.python}
-          '2': {name: support.other.format.python}
+          '2': {name: storage.type.format.python}
 
       - include: '#fstring-terminator-${line}-tail'
 
@@ -145,25 +153,25 @@ repository:
     end: (?=})${fguard}
     beginCaptures:
       '1': {name: storage.type.format.python}
-      '2': {name: support.other.format.python}
+      '2': {name: storage.type.format.python}
 
     patterns:
       - include: '#fstring-illegal-${line}-brace'
       - include: '#fstring-${line}-brace'
-      - name: support.other.format.python
+      - name: storage.type.format.python
         match: ([bcdeEfFgGnosxX%])(?=})
-      - name: support.other.format.python
+      - name: storage.type.format.python
         match: (\.\d+)
-      - name: support.other.format.python
+      - name: storage.type.format.python
         match: (,)
-      - name: support.other.format.python
+      - name: storage.type.format.python
         match: (\d+)
-      - name: support.other.format.python
+      - name: storage.type.format.python
         match: (\#)
-      - name: support.other.format.python
+      - name: storage.type.format.python
         match: ([-+ ])
-      - name: support.other.format.python
+      - name: storage.type.format.python
         match: ([<>=^])
-      - name: support.other.format.python
+      - name: storage.type.format.python
         match: (\w)
 ...
diff --git a/misc/scopes b/misc/scopes
index 85bc470e..72e0d629 100644
--- a/misc/scopes
+++ b/misc/scopes
@@ -149,7 +149,6 @@ string.regexp.quoted.single.python
 support.function.builtin.python
 support.function.magic.python
 support.other.escape.special.regexp
-support.other.format.python
 support.other.match.any.regexp
 support.other.match.begin.regexp
 support.other.match.end.regexp
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 4e139381..38958186 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -6151,9 +6151,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][7].value).toBe("10");
       expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
       expect(tokens[0][8].value).toBe(":");
-      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][9].value).toBe("#");
-      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][10].value).toBe("{");
       expect(tokens[0][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][11].value).toBe("3");
@@ -6185,7 +6185,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][24].value).toBe("}");
       expect(tokens[0][24].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][25].value).toBe("x");
-      expect(tokens[0][25].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][25].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][26].value).toBe("}");
       expect(tokens[0][26].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][27].value).toBe("'");
@@ -6419,7 +6419,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].value).toBe("value");
       expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python"]);
       expect(tokens[0][5].value).toBe(":");
-      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][6].value).toBe("{");
       expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][7].value).toBe("60");
@@ -6435,7 +6435,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][12].value).toBe("!s");
       expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][13].value).toBe(":2");
-      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][14].value).toBe("}");
       expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][15].value).toBe("{");
@@ -6474,7 +6474,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].value).toBe("value");
       expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python"]);
       expect(tokens[0][5].value).toBe(":");
-      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][6].value).toBe("{");
       expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][7].value).toBe("60");
@@ -6490,7 +6490,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][12].value).toBe("!s");
       expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][13].value).toBe(":2");
-      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][14].value).toBe("}");
       expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][15].value).toBe("{");
@@ -6531,7 +6531,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].value).toBe("value");
       expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python"]);
       expect(tokens[0][5].value).toBe(":");
-      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][6].value).toBe("{");
       expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][7].value).toBe("60");
@@ -6547,7 +6547,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][12].value).toBe("!s");
       expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][13].value).toBe(":2");
-      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][14].value).toBe("}");
       expect(tokens[0][14].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][15].value).toBe("{");
@@ -7119,7 +7119,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][10].value).toBe("]");
       expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","punctuation.definition.list.end.python"]);
       expect(tokens[0][11].value).toBe(":X>+10d");
-      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][12].value).toBe("}");
       expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][13].value).toBe("\"");
@@ -7149,7 +7149,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][11].value).toBe("!s");
       expect(tokens[1][11].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[1][12].value).toBe(":X>+10d");
-      expect(tokens[1][12].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[1][12].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[1][13].value).toBe("}");
       expect(tokens[1][13].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][14].value).toBe("\"");
@@ -7295,7 +7295,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][18].value).toBe("!r");
       expect(tokens[0][18].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][19].value).toBe(":f");
-      expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][20].value).toBe("}");
       expect(tokens[0][20].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][21].value).toBe(" times");
@@ -7346,7 +7346,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][18].value).toBe("!r");
       expect(tokens[0][18].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][19].value).toBe(":f");
-      expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][20].value).toBe("}");
       expect(tokens[0][20].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][21].value).toBe(" times");
@@ -7399,7 +7399,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][12].value).toBe("!r");
       expect(tokens[1][12].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[1][13].value).toBe(":f");
-      expect(tokens[1][13].scopes).toEqual(["source.python","meta.fstring.python","support.other.format.python"]);
+      expect(tokens[1][13].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[1][14].value).toBe("}");
       expect(tokens[1][14].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][15].value).toBe(" times");
@@ -12867,7 +12867,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][5].value).toBe("{0[ ]");
       expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][6].value).toBe(":X>+10d");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[0][7].value).toBe("}");
       expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][8].value).toBe("\"");
@@ -12887,7 +12887,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][6].value).toBe("!s");
       expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[1][7].value).toBe(":X>+10d");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[1][8].value).toBe("}");
       expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][9].value).toBe("\"");
@@ -12905,7 +12905,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][5].value).toBe("{0[ ]");
       expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][6].value).toBe(":");
-      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[2][7].value).toBe("Xd>+10d");
       expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][8].value).toBe("}");
@@ -13276,7 +13276,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][6].value).toBe("{");
       expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][7].value).toBe(":");
-      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[0][8].value).toBe("%Y-%m-%d %H:%M:%S");
       expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][9].value).toBe("}");
@@ -13300,7 +13300,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][6].value).toBe("{0");
       expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][7].value).toBe(":");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[1][8].value).toBe("{fill}");
       expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][9].value).toBe("{align}");
@@ -13333,7 +13333,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][6].value).toBe("{0");
       expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][7].value).toBe(":");
-      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[0][8].value).toBe("{width}");
       expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][9].value).toBe("{base}");
@@ -13359,7 +13359,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][6].value).toBe("{0");
       expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][7].value).toBe(":");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","support.other.format.python"]);
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[1][8].value).toBe("$20");
       expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][9].value).toBe("}");
diff --git a/test/fstrings/comment4.py b/test/fstrings/comment4.py
index 7f298de9..793efc35 100644
--- a/test/fstrings/comment4.py
+++ b/test/fstrings/comment4.py
@@ -11,8 +11,8 @@
 '             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 10            : constant.numeric.dec.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-:             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, support.other.format.python
-#             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, support.other.format.python
+:             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.format.python
+#             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.format.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 3             : constant.numeric.dec.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
               : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
@@ -28,7 +28,7 @@
               : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 width         : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-x             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, support.other.format.python
+x             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.format.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 '             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
 ,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
diff --git a/test/fstrings/nested2.py b/test/fstrings/nested2.py
index fe92f4e1..276501e2 100644
--- a/test/fstrings/nested2.py
+++ b/test/fstrings/nested2.py
@@ -8,7 +8,7 @@
 result:       : meta.fstring.python, source.python, string.interpolated.python, string.quoted.single.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 value         : meta.fstring.python, source.python
-:             : meta.fstring.python, source.python, support.other.format.python
+:             : meta.fstring.python, source.python, storage.type.format.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 60            : constant.numeric.dec.python, meta.fstring.python, source.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
@@ -16,7 +16,7 @@
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 16            : constant.numeric.dec.python, meta.fstring.python, source.python
 !s            : meta.fstring.python, source.python, storage.type.format.python
-:2            : meta.fstring.python, source.python, support.other.format.python
+:2            : meta.fstring.python, source.python, storage.type.format.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 '             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
diff --git a/test/fstrings/nested3.py b/test/fstrings/nested3.py
index 80d07e26..607c38ca 100644
--- a/test/fstrings/nested3.py
+++ b/test/fstrings/nested3.py
@@ -9,7 +9,7 @@
 result:       : meta.fstring.python, source.python, string.interpolated.python, string.quoted.single.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 value         : meta.fstring.python, source.python
-:             : meta.fstring.python, source.python, support.other.format.python
+:             : meta.fstring.python, source.python, storage.type.format.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 60            : constant.numeric.dec.python, meta.fstring.python, source.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
@@ -17,7 +17,7 @@
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 16            : constant.numeric.dec.python, meta.fstring.python, source.python
 !s            : meta.fstring.python, source.python, storage.type.format.python
-:2            : meta.fstring.python, source.python, support.other.format.python
+:2            : meta.fstring.python, source.python, storage.type.format.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 '             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
diff --git a/test/fstrings/nested4.py b/test/fstrings/nested4.py
index bd5325c7..01b9cd16 100644
--- a/test/fstrings/nested4.py
+++ b/test/fstrings/nested4.py
@@ -10,7 +10,7 @@ def foo(): pass
 result:       : meta.fstring.python, source.python, string.interpolated.python, string.quoted.multi.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 value         : meta.fstring.python, source.python
-:             : meta.fstring.python, source.python, support.other.format.python
+:             : meta.fstring.python, source.python, storage.type.format.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 60            : constant.numeric.dec.python, meta.fstring.python, source.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
@@ -18,7 +18,7 @@ def foo(): pass
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 16            : constant.numeric.dec.python, meta.fstring.python, source.python
 !s            : meta.fstring.python, source.python, storage.type.format.python
-:2            : meta.fstring.python, source.python, support.other.format.python
+:2            : meta.fstring.python, source.python, storage.type.format.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 '             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
diff --git a/test/fstrings/simple1.py b/test/fstrings/simple1.py
index 813e7270..d7281270 100644
--- a/test/fstrings/simple1.py
+++ b/test/fstrings/simple1.py
@@ -16,7 +16,7 @@
 [             : meta.fstring.python, punctuation.definition.list.begin.python, source.python
               : meta.fstring.python, source.python
 ]             : meta.fstring.python, punctuation.definition.list.end.python, source.python
-:X>+10d       : meta.fstring.python, source.python, support.other.format.python
+:X>+10d       : meta.fstring.python, source.python, storage.type.format.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 "             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
 a             : source.python
@@ -31,7 +31,7 @@
               : meta.fstring.python, source.python
 ]             : meta.fstring.python, punctuation.definition.list.end.python, source.python
 !s            : meta.fstring.python, source.python, storage.type.format.python
-:X>+10d       : meta.fstring.python, source.python, support.other.format.python
+:X>+10d       : meta.fstring.python, source.python, storage.type.format.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 "             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
 a             : source.python
diff --git a/test/fstrings/simple3.py b/test/fstrings/simple3.py
index a67ea19c..6ea20170 100644
--- a/test/fstrings/simple3.py
+++ b/test/fstrings/simple3.py
@@ -22,7 +22,7 @@
 23            : constant.numeric.dec.python, meta.fstring.python, source.python
               : meta.fstring.python, source.python
 !r            : meta.fstring.python, source.python, storage.type.format.python
-:f            : meta.fstring.python, source.python, support.other.format.python
+:f            : meta.fstring.python, source.python, storage.type.format.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
  times        : meta.fstring.python, source.python, string.interpolated.python, string.quoted.single.python
 '             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
diff --git a/test/fstrings/simple4.py b/test/fstrings/simple4.py
index 73891eb0..f0630423 100644
--- a/test/fstrings/simple4.py
+++ b/test/fstrings/simple4.py
@@ -22,7 +22,7 @@
 23            : constant.numeric.dec.python, meta.fstring.python, source.python
               : meta.fstring.python, source.python
 !r            : meta.fstring.python, source.python, storage.type.format.python
-:f            : meta.fstring.python, source.python, support.other.format.python
+:f            : meta.fstring.python, source.python, storage.type.format.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
  times        : meta.fstring.python, source.python, string.interpolated.python, string.quoted.multi.python
 '''           : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.multi.python
diff --git a/test/fstrings/simple5.py b/test/fstrings/simple5.py
index 42d3f400..074af929 100644
--- a/test/fstrings/simple5.py
+++ b/test/fstrings/simple5.py
@@ -24,7 +24,7 @@
 23            : constant.numeric.dec.python, meta.fstring.python, source.python
               : meta.fstring.python, source.python
 !r            : meta.fstring.python, source.python, storage.type.format.python
-:f            : meta.fstring.python, source.python, support.other.format.python
+:f            : meta.fstring.python, source.python, storage.type.format.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
  times        : meta.fstring.python, source.python, string.interpolated.python, string.quoted.multi.python
 '''           : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.multi.python
diff --git a/test/strings/format1.py b/test/strings/format1.py
index beba8cff..b9b8e6e0 100644
--- a/test/strings/format1.py
+++ b/test/strings/format1.py
@@ -10,7 +10,7 @@
               : source.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 {0[ ]         : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:X>+10d       : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python, support.other.format.python
+:X>+10d       : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
 }             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
@@ -20,7 +20,7 @@
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 {0[ ]         : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 !s            : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
-:X>+10d       : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python, support.other.format.python
+:X>+10d       : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
 }             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
@@ -29,7 +29,7 @@
               : source.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 {0[ ]         : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python, support.other.format.python
+:             : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
 Xd>+10d       : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 }             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
diff --git a/test/strings/format4.py b/test/strings/format4.py
index b33daf32..e135cf03 100644
--- a/test/strings/format4.py
+++ b/test/strings/format4.py
@@ -11,7 +11,7 @@
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 qqq           : source.python, string.quoted.single.python
 {             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python, support.other.format.python
+:             : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
 %Y-%m-%d %H:%M:%S : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 }             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 www           : source.python, string.quoted.single.python
@@ -23,7 +23,7 @@
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 qqq           : source.python, string.quoted.single.python
 {0            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python, support.other.format.python
+:             : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
 {fill}        : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 {align}       : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 16            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
diff --git a/test/strings/format5.py b/test/strings/format5.py
index 5d7194df..0c3f6bb4 100644
--- a/test/strings/format5.py
+++ b/test/strings/format5.py
@@ -12,7 +12,7 @@
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 qqq           : source.python, string.quoted.single.python
 {0            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python, support.other.format.python
+:             : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
 {width}       : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 {base}        : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 }             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
@@ -25,7 +25,7 @@
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 qqq           : source.python, string.quoted.single.python
 {0            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python, support.other.format.python
+:             : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
 $20           : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 }             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 www           : source.python, string.quoted.single.python

From fdbf44b530e59c15957f948a70aa06bfb5654f10 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Wed, 29 Mar 2017 21:50:59 -0400
Subject: [PATCH 16/65] Prepare 1.0.9 release

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 5f473ced..efb9d141 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "MagicPython",
-  "version": "1.0.8",
+  "version": "1.0.9",
   "engines": {
     "atom": "*",
     "node": "*",

From b8998dc63df4c145d7b5e7e46e33efd872fb0b6c Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yselivanov@gmail.com>
Date: Tue, 25 Apr 2017 11:06:12 -0700
Subject: [PATCH 17/65] Update LICENSE

---
 LICENSE | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/LICENSE b/LICENSE
index 79a03ca5..e6b42c6f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
 The MIT License
 
-Copyright (c) 2015 MagicStack Inc.  http://magic.io
+Copyright (c) 2015-present MagicStack Inc.  http://magic.io
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal

From 65a7b4cc0fc4b4fa08806d6d6adfd93b707f54b0 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Thu, 27 Apr 2017 15:40:24 -0400
Subject: [PATCH 18/65] travis: Use recent nodejs to run tests

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 100771e4..bc26510f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
 language: node_js
 
 node_js:
-  - 0.10
+  - "7"
 
 install:
   - make

From a7d329dc4a860e589083c3b354bd8b9b51b8afbd Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Thu, 27 Apr 2017 15:59:24 -0400
Subject: [PATCH 19/65] build: Bump syntaxdev dep to 0.0.16

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 3a581363..2d09f37c 100644
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,7 @@ test: ci-test
 	atom -t .
 
 devenv:
-	npm install syntaxdev@0.0.15
+	npm install syntaxdev@0.0.16
 
 release:
 	./node_modules/.bin/syntaxdev build-plist --in grammars/src/MagicPython.syntax.yaml --out grammars/MagicPython.tmLanguage

From ed68ac42c5cadb9b56902f03310d8d4afcdb012f Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Thu, 27 Apr 2017 16:01:59 -0400
Subject: [PATCH 20/65] travis: Fix build env

---
 .travis.yml | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index bc26510f..05da1abe 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,17 @@
 language: node_js
 
 node_js:
-  - "7"
+  - "6"
+
+env:
+  - CXX=g++-4.8
+
+addons:
+  apt:
+    sources:
+      - ubuntu-toolchain-r-test
+    packages:
+      - g++-4.8
 
 install:
   - make

From 34427bcba880c804484dce4d5da2431a64c73e2b Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Wed, 3 May 2017 15:12:36 -0400
Subject: [PATCH 21/65] Fix double quote autoclosing issue with docstring
 quotes.

---
 settings/sublime/Default.sublime-keymap | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/settings/sublime/Default.sublime-keymap b/settings/sublime/Default.sublime-keymap
index 50c1b423..3a0ae806 100644
--- a/settings/sublime/Default.sublime-keymap
+++ b/settings/sublime/Default.sublime-keymap
@@ -5,7 +5,7 @@
             { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
             { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
             { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|>|$)", "match_all": true },
-            { "key": "preceding_text", "operator": "regex_contains", "operand": "(?:[bfruBFRU]|[^'[:alnum:]_])$", "match_all": true },
+            { "key": "preceding_text", "operator": "regex_contains", "operand": "(?:[bfruBFRU]|[^\"[:alnum:]_])$", "match_all": true },
             { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.double - punctuation.definition.string.end", "match_all": true },
             { "key": "eol_selector", "operator": "equal", "operand": "source.python", "match_all": true }
         ]

From cba112e1620dc50f7ed458497ecab925d1501f6c Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Wed, 3 May 2017 15:39:13 -0400
Subject: [PATCH 22/65] Prepare 1.0.10 release

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index efb9d141..432eb0b8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "MagicPython",
-  "version": "1.0.9",
+  "version": "1.0.10",
   "engines": {
     "atom": "*",
     "node": "*",

From 68c88ccfc21bc720e8e17137672d4c29b716cbd3 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Fri, 5 May 2017 19:32:04 -0400
Subject: [PATCH 23/65] Tweak symbol list.

Elide arguments for extra long function definitions.
---
 settings/sublime/Symbol List.tmPreferences | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/settings/sublime/Symbol List.tmPreferences b/settings/sublime/Symbol List.tmPreferences
index e832b863..987e0f72 100644
--- a/settings/sublime/Symbol List.tmPreferences	
+++ b/settings/sublime/Symbol List.tmPreferences	
@@ -15,7 +15,7 @@
         # transform into 'class Classname' form
         s/(class)\s+([[:alpha:]_]\w*)\s*.*/$1 $2/g;
 
-        # transform into '[async] funciton_name(args,...)' form
+        # transform into '[async] funciton_name(args,...)' long form
         s/(?x)
             def \s+
                 ([[:alpha:]_]\w*) \s* \(
@@ -24,6 +24,13 @@
 
         # remove extra whitespace in arg list (except leading)
         s/(\S)\s{2,}/$1 /g;
+
+        # transform into short form
+        s/(?x)
+            (class\s|async\s)? (\w+\()
+                (.{80})(.+)
+            (\))$
+            /$1$2$3\.\.\.$5/g;
 		</string>
 	</dict>
 	<key>uuid</key>

From 7cb46598c38a0823f3ff04b30dd5ee32a905347e Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Wed, 19 Jul 2017 16:22:19 -0400
Subject: [PATCH 24/65] Fix travis-ci build. Fixes #93.

---
 .travis.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index 05da1abe..bf2912a0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,8 @@ node_js:
 env:
   - CXX=g++-4.8
 
+dist: trusty
+
 addons:
   apt:
     sources:

From ffab3f1ec0272e6ae6546ffd21eb84a49328930d Mon Sep 17 00:00:00 2001
From: tennyson-mccalla <tennyson.mccalla@gmail.com>
Date: Wed, 19 Jul 2017 18:12:22 -0400
Subject: [PATCH 25/65] Sync Atom snippets with language-python (#94)

---
 snippets/atom.cson | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/snippets/atom.cson b/snippets/atom.cson
index 41827a5e..0f03f31b 100644
--- a/snippets/atom.cson
+++ b/snippets/atom.cson
@@ -34,9 +34,18 @@
   '#!/usr/bin/env python':
     'prefix': 'env'
     'body': '#!/usr/bin/env python\n'
+  '#!/usr/bin/env python3':
+    'prefix': 'env3'
+    'body': '#!/usr/bin/env python3\n'
   '# coding=utf-8':
     'prefix': 'enc'
-    'body': '# coding=utf-8\n'
+    'body': '# -*- coding: utf-8 -*-\n'
+  'Import':
+    'prefix': 'im'
+    'body': 'import ${1:package/module}'
+  'From/Import':
+    'prefix': 'fim'
+    'body': 'from ${1:package/module} import ${2:names}'
   'Assert Equal':
     'prefix': 'ase'
     'body': 'self.assertEqual(${1:expected}, ${2:actual}${3:, \'${4:message}\'})$0'
@@ -97,6 +106,9 @@
   'while':
     'prefix': 'while'
     'body': 'while ${1:condition}:\n\t${2:pass}'
+  'with statement':
+    'prefix': 'with'
+    'body': 'with ${1:expression} as ${2:target}:\n\t${3:pass}'
   'Try/Except/Else/Finally':
     'prefix': 'tryef'
     'body': 'try:\n\t${1:pass}\nexcept${2: ${3:Exception} as ${4:e}}:\n\t${5:raise}\nelse:\n\t${6:pass}\nfinally:\n\t${7:pass}'
@@ -118,12 +130,21 @@
   'Dictionary Comprehension':
     'prefix': 'dc'
     'body': '{${1:key}: ${2:value} for ${3:key}, ${4:value} in ${5:variable}}'
+  'Set Comprehension':
+    'prefix': 'sc'
+    'body': '{${1:value} for ${2:value} in ${3:variable}}'
   'PDB set trace':
     'prefix': 'pdb'
     'body': 'import pdb; pdb.set_trace()\n'
   'iPDB set trace':
     'prefix': 'ipdb'
     'body': 'import ipdb; ipdb.set_trace()\n'
+  'rPDB set trace':
+    'prefix': 'rpdb'
+    'body': 'import rpdb2; rpdb2.start_embedded_debugger(\'${1:debug_password}\')$0'
+  'PuDB set trace':
+    'prefix': 'pudb'
+    'body': 'import pudb; pudb.set_trace()'
   '__magic__':
     'prefix': '__'
     'body': '__${1:init}__'

From 7fb0aa5b2e0ec906863d0b358c5a5648e28822b3 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 21 Jul 2017 13:04:09 -0400
Subject: [PATCH 26/65] Highlight __traceback__

---
 grammars/MagicPython.cson            |  2 +-
 grammars/MagicPython.tmLanguage      |  2 +-
 grammars/src/MagicPython.syntax.yaml |  2 +-
 test/atom-spec/python-spec.js        | 12 +++++++++---
 test/builtins/builtins3.py           |  4 ++++
 5 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 65b36733..efdd9583 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -1829,7 +1829,7 @@ repository:
             | metaclass | methods | module | mro | name
             | qualname | self | signature | slots | subclasses
             | version | weakref | wrapped | annotations | classcell
-            | spec | path | package | future
+            | spec | path | package | future | traceback
           )__
         )\\b
       
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 784b4894..7291caf0 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -2813,7 +2813,7 @@ indirectly through syntactic constructs
       | metaclass | methods | module | mro | name
       | qualname | self | signature | slots | subclasses
       | version | weakref | wrapped | annotations | classcell
-      | spec | path | package | future
+      | spec | path | package | future | traceback
     )__
   )\b
 </string>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index b43b8f84..f39918b8 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -1370,7 +1370,7 @@ repository:
             | metaclass | methods | module | mro | name
             | qualname | self | signature | slots | subclasses
             | version | weakref | wrapped | annotations | classcell
-            | spec | path | package | future
+            | spec | path | package | future | traceback
           )__
         )\b
     captures:
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 38958186..0359e613 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -130,7 +130,7 @@ describe("Grammar Tests", function() {
 
   it("test/builtins/builtins3.py", 
     function() {
-      tokens = grammar.tokenizeLines("__all__ = ['bar', 'baz']\nsome.__bases__\nsome.__class__\nassert __debug__\n__builtins__\n__builtins__.len\nprint(__builtins__)\nsome.__dict__\nsome.__doc__\nsome.__file__\nsome.__members__\nsome.__metaclass__\nsome.__methods__\nsome.__module__\nsome.__mro__\nsome.__name__\nsome.__slots__\nsome.__subclasses__\nsome.__version__\nsome.__weakref__\nsome.__qualname__\nsome.__code__\nsome.__wrapped__\nsome.__signature__\nsome.__defaults__\nsome.__func__\nsome.__self__\nsome.__kwdefaults__\nsome.__matmul__\nsome.__imatmul__\nsome.__rmatmul__\nsome.__annotations__\nsome.__init_subclass__\nsome.__set_name__\nsome.__fspath__\nsome.__classcell__\nsome.__bytes__\nsome.__spec__\nsome.__path__\nsome.__prepare__\nsome.__package__\nsome.__notspecial__")
+      tokens = grammar.tokenizeLines("__all__ = ['bar', 'baz']\nsome.__bases__\nsome.__class__\nassert __debug__\n__builtins__\n__builtins__.len\nprint(__builtins__)\nsome.__dict__\nsome.__doc__\nsome.__file__\nsome.__members__\nsome.__metaclass__\nsome.__methods__\nsome.__module__\nsome.__mro__\nsome.__name__\nsome.__slots__\nsome.__subclasses__\nsome.__version__\nsome.__weakref__\nsome.__qualname__\nsome.__code__\nsome.__wrapped__\nsome.__signature__\nsome.__defaults__\nsome.__func__\nsome.__self__\nsome.__kwdefaults__\nsome.__matmul__\nsome.__imatmul__\nsome.__rmatmul__\nsome.__annotations__\nsome.__init_subclass__\nsome.__set_name__\nsome.__fspath__\nsome.__classcell__\nsome.__bytes__\nsome.__spec__\nsome.__path__\nsome.__prepare__\nsome.__package__\nsome.__traceback__\nsome.__notspecial__")
       expect(tokens[0][0].value).toBe("__all__");
       expect(tokens[0][0].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[0][1].value).toBe(" ");
@@ -401,8 +401,14 @@ describe("Grammar Tests", function() {
       expect(tokens[41][0].scopes).toEqual(["source.python"]);
       expect(tokens[41][1].value).toBe(".");
       expect(tokens[41][1].scopes).toEqual(["source.python"]);
-      expect(tokens[41][2].value).toBe("__notspecial__");
-      expect(tokens[41][2].scopes).toEqual(["source.python"]);
+      expect(tokens[41][2].value).toBe("__traceback__");
+      expect(tokens[41][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[42][0].value).toBe("some");
+      expect(tokens[42][0].scopes).toEqual(["source.python"]);
+      expect(tokens[42][1].value).toBe(".");
+      expect(tokens[42][1].scopes).toEqual(["source.python"]);
+      expect(tokens[42][2].value).toBe("__notspecial__");
+      expect(tokens[42][2].scopes).toEqual(["source.python"]);
     });
 
   it("test/builtins/builtins4.py", 
diff --git a/test/builtins/builtins3.py b/test/builtins/builtins3.py
index 68036b64..fd3db478 100644
--- a/test/builtins/builtins3.py
+++ b/test/builtins/builtins3.py
@@ -39,6 +39,7 @@
 some.__path__
 some.__prepare__
 some.__package__
+some.__traceback__
 some.__notspecial__
 
 
@@ -179,4 +180,7 @@
 __package__   : source.python, support.variable.magic.python
 some          : source.python
 .             : source.python
+__traceback__ : source.python, support.variable.magic.python
+some          : source.python
+.             : source.python
 __notspecial__ : source.python

From da1a537acab2cde0748d47418f2d13b5d5352f48 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 21 Jul 2017 13:05:08 -0400
Subject: [PATCH 27/65] Prepare 1.0.11 release

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 432eb0b8..b7b86461 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "MagicPython",
-  "version": "1.0.10",
+  "version": "1.0.11",
   "engines": {
     "atom": "*",
     "node": "*",

From d39070f6212b43803c67d61110dfd243b4a21923 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 21 Jul 2017 14:01:13 -0400
Subject: [PATCH 28/65] Use a PNG icon for vscode extensions gallery

---
 icon.png     | Bin 0 -> 5228 bytes
 icon.svg     |  23 -----------------------
 package.json |   2 +-
 3 files changed, 1 insertion(+), 24 deletions(-)
 create mode 100644 icon.png
 delete mode 100644 icon.svg

diff --git a/icon.png b/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..c49edec988b74670e30890b71c97e7ff7d9be412
GIT binary patch
literal 5228
zcmZ`-c{r5q+kVErWGAvsQbx!Kp|VU_Ls>GEWt50g5n-6YBoUP*TfJf|WqncEB4$Lg
zl~J-}V$g^b!;CS8!T0EWzwh||`2GI4pXE57=eh6uy3Xr7&+AEYJYy{)BrgO2fXFEu
z3uo|*+Zh6U;IYH>Vjp;dggRTF1giTLe}XqW{wGeK0DzaN!kmk|;Jsk5&G}FO5bf9*
zkglLIUjUGXoU%CKf<`Um{S1}qYD#4As|1>jr5dCG2d@eF95(Q&N9^5wN-ntV{VAMW
zT*d|dOZSnGOKqd0Zw>gQJi_2v(lhsL?^S*4Hb}`EMY3GIMm8^0*knzRgGej(q^FBd
z7ESve-0Dx974AH$=buj@57O*ObNqUjKj667b}B&Rng1~Q>%<U0KOAs;Suo;<g1cz{
zzSCUKUpTDxX-I5_G3;@xSvqT2fEar0@F6Zo&p{!i9baJ~OGlr%&F3DGcc&pbsQoGT
z$VG!!+a|Ufq>1{qpT`FhI8=GR;aZ|<i-;aeCCJGg-(-6wa{aW8X#VZ>D!BQ_^^UZ2
zY%LcpW!yB?c#2?uq{J6^p&O_?&U=WvM*LF{qAS$!qBfnOpu>N3jZng&oSISnh@rd~
z4dwkS4N4S!7{6X9QRcp(C~X)f$O_fadCui%8X;4+OH`_fc4D?rtbkjh2R7H&$W@?0
zTrTfRvk3Pt`mzd5^a*K}ScrJ~L=vJNxDfZmAwLePOyJGChcFcZ;1p2+j^}HG;i2mu
z_?KL5)JC4}Qpk%L!{5y|XpyUlsJqF2Z|)LRs^6Ic=a`{lD8olI9)ul12{^=-EsU8B
zG>|R0+TnzL)_i&mGi~)Zx8pG3+oSFKlv40BOFd%7v|ru+=EU2aW>~sgVbr9Sv>|-=
zR<)4?8JM&PS|w;!W8+?8VL%AGh+&%Hz`Zv;)tu-Zvyj5b{HqF9SVk~k+n7FijeFq5
zBBBCouo6o5H`zS)fwRoZ%l>=)2(@;8<WUg+g*nA9;*tv9(p!Yr;$)z1p_SS#o5#w?
zO)2p#EB9dNxzA|OtAKzHYuDL5<00()`7U7BR<^TlY^}f9cMC0U$Ik<M)QJtVd!}a7
zl2e8x*-rvk`cyKcOj+)B#n#0s!u#9j`1ZaG$Z&~a3>=*DN6$y4#&?6EhEcAwTxMzk
zmmru_dqY?JhWwG2y8zToMm+{;*C1@xadw!{uIg?4y^)$*kCFWipl50s1Z#p4jxIwI
zVja2avj^9lAAOQ-^i%T+N}aPytY0K<h78epM5^%iijgUN#p0bJSe@45PW!ebtbyml
zWu#^{nrU-(IXD$LX_)!V%~A&e8!CT2<|4haA@6oCA?Ke(AQ)|$C)uOF+-d}fUy>Wc
zLdO?*d#oir9E8DHr}yBl*BF_b!J(MV^O&0WiP9i><0lGi9whrN5HJuAL9n%e25fj?
z=@s$|eV(viqDR5_`8JI-a<}#EB-Y`YAPrTtw*+FO9OX?6V+A_aV_|vAISpC~7A!!2
z!6>lLe+Zw8q6i{zoZgebmqN&k#2BVs%ady?Pqr(df0@(3(ZF+hw=&u(@<*0;wGHQZ
zvbO;7WqrVwz5oRD7}A(|3<4s?QU#bF0DNst71ryiwS^P}co9w4G{B2*4VNYP0}U<v
zq3hS#O@#W&1Nb&D7~+4na1SEh6Tx+1FCIzE#vTXM=;xVadY@q@Bf-(0J6LPyD_-C_
zUVU49(%s07qYFa@0NO7@n$e}hzIy1tKI@~CKN|&qF1)xQc)zMc+OxyqtIuHU)9SIR
zan7TUhiyNWTynIoFm?ee0c9$Jb0EyMc%uXmE#>1e?xzS+fH`|67bS7S?5YrCG^SS+
z_x=GT8y?7715xfh>?VNFdJFE+A2N`MkASo>IcRU<o}drLVfnfnr6ci%Xx-t(n^J^=
zJ;bnn7HJK{d7+uh)(ce%6i22Ri?YlXkv^PN_t%k;N1vJz#G8NQU<fcTU3ma&Q#+Mp
zt`o6+r1{zXL-T3lV_CfprQ^cs_~r1_d!-P8bnju-tJ!mfqdh^1`g@+)b8af_x^5pu
zAZ0$_1v(>?o2RsXJfnZDP*!D^FQ8m8(Qyq}*G(=qXCRe6D26)_OD97fb1onETY2c0
zPt#Xf09?YWxjfrH)=bG(&FW<Yt$xvln<=ysg5N{;5pNY=0Uo2<4ehrK9&==0$-KW&
zy@ajNzQPO4V3fxnfdTjfbaOCZBL8MzgKh$`$qM3~d_6l_&Wo#wLT$O;k6o2A$Ve|B
zGscg}@#Au8n3E+%*iQpBFucg-TRL*A)xLW~3`d+73?FjX3cRlxOULI<PUS?uh{*l=
zv`rmYo3!e>%~}BqYjS1~Q15Bv7T@cAYr=mA)Wi{otQrMeTE*;4Y-`ehHGBTMGKp1L
zqy%^-4>imd9RTN$r{@8WyZwi14&afoH=?3Vffj5%utdL8Igv$7e{nk`5?$@Dpb@~2
zGpYO84bx%k1Ey>z=KAy=V!|KRx&k;;OB*oz*l!_e$X0s-l39(VdwH8cD6tKE?iro=
z3-N_Az~5Ub+_Y!C;5@1nL0kfsD+^?S9kNwo$J_Vh@VC{?x6)xmcZYNQrLji`Yx8vK
zxF%zLkB2Vg-v&YMP8S@be;t6Qfk3mMOKhEU2bsLoiD}QFnx)kT(@G}n4%TsruXcxP
zQwBQwNW;1}wj<4y*aERyRlr&zR@x!>os@Kia;L}Nw-fO-pO1;C^Y8tgzA!g2@Ei^<
zC<W^PIL~-M#P3_%8gSl+8q+8$^tuFWV9{(cY!sO~4I^5(O1ZxMsalnPowraC*NohF
zMrRj#TNBXlgL+asbZ@kVJ80!Qy;^k3|IVi1CCh~tyhhW4daRe@H%#KQf@xN3+;zKV
zfVxGatT*8fb}=ps%5ZNLKvOI#WwxW{Uhoi@rQ_3ro<n-<3>Gwz)&*r=(-Z(-_^xo2
zn_5|iu>}Kw*JNLt8+k<ILs*(Re>*}|?5j=*Ny6UQ$?&q#)ZuoaIgj&G%P{kU06I6P
zrxY@f4vL!gA3$6I_R~A{Vz}8nYIwfAmITxrSW(%h=)B+TOAPEZyCSDYtQv$QRW`MK
z8DHro?<$1w`DE3&9ttAk|CmOYn)_ib($-apu1H#T+V`<+-jD9JoZ+nn)4KC%WXyz|
zStyNLXObclVoboLMu0Kx4tZ0mZl<u1k1sM{9W!YN5Zg}AtMI2!F`nxzr;m|8WO3o7
z+A?=yq7TLd5AKZs1Ag|w7bE*awSrLd`-&pj>iLuRVCrrr8L87bQp?%cHLRfVn#Dp~
znlmsKOV4&QRcWN3CAS)_t{?n67IHb5wrla{nYIqNQ}cXU>a<`AI<9Wsi@kK-(9&;T
znKZB+iSPYi!j~nj9b%uQ4Ob&x@w6<R)$e=bKHGo1&uH0{EwqqlL(t4$+LJ+)yD)97
z(?aa8jg}~cw230rK-BEeuN6qY3UwGO`Zy49dVN@l`C&bs(RIv-ErcZXxm85fU?0!L
z36l)bt0yc1fTj9t_5|A+JiIa7PZ}P}mn?ZY|I+JNf7Lzfyh!{H3kMgby0Y4C2q#+N
zoBWmK---7I02i%MIqg416W0Vzc#JOi^-*evNisg&GcAPUxW&RteY%Z=XViEzvpIJ&
z$vN#b!FWD^^5M$ZqF?<8tbj9r2)6grhGv;(s6cP_V#2EfZ;Ug;X)E+%CCBzTc{<MR
zmlmJa?z?vmp`30$UmEpNUfiGM@Xo(^J}(J%b;yG*3vfob<S?4p>j-cQt=M^bZET?I
zwzzrc{2j;7Y#!;XWHIcQm8$9l5E3GZSZiYy?gg)N;G45jKi+PNb!=ZvatG=_OJjJ2
zMWqMwkv=D<RNmt0q{IZiq<WJ2te1JLjZYM})>4bnaW(T#uxn(oDKdG=jl07EVwadn
z^{*Ze1)+qNk^CiU?zC&0Pi*4LQTi=SPZJX;p~+6;NiwU4bP@woraKvDP)@NIzkhAt
z{NePNXEh4c%^g-OIAB&k0;f%=e1l_cB%#?Yj4j*d<{!D3+%_-YD?&t5cxYdp?)XI0
zv>>6Pks9H+82kA4QGoFD>$yMr>;WlLGUk6CI{fUn17$wywV|zOnd60HOY|_;`EKej
zx7Mo|m;&949ePm8@UOEec>Dk`83y>zHO|Zyjdz?<CPJ%voaI_=MYA1I$8?tCAGm>B
zd18nm)rteBBSGZw+?U)GOu8IFl!$A9>Anq$Q!-uC^*7@hG!a8Pwr>B{%>)kZlu}%d
z_jGCX!N~4l<-Nbu*u|B`J+Gx76kMYX(0W1VMp^8kx&^IP=UcL$93^fnyS4sX11D3+
zZwhuQZ_wa%So3hGmZdsx!AuY1DMvpl8V2})R*kX!(h_?-;atH%6%fA>?<z(ADLvo9
zR=e^j4T_8yzJK3`c;UoK<1XiTXW-Fh7Z&8DpnafvRB$R_`K)WKd4ZqhcO_3x%_z8-
zz|GoMwaa!g`b=i^h89E7LBbYN_A_!AbmtTyAOnA+CN=XzxLg0^z;-NN;_%7z=I#oV
z8l_-9l70RLtp!N}A<+)Y=I}>!90x280!h^|Nq+>PvoSodA(B#(*R+RtWvCBKL39cE
zcq9nAsf^un#NDP4i%c$DZ2Tz=Q01&ZIh=f$mz=+ue|?KaNs=pcM1tzAA4qeihE7k_
ze2iB^Z&=pb{jh}~<nf9(srUOg>_PKm0h%Au;_s~fU!e{4+vVq<+DNT|TnnO9HD8C9
zeEdAf)=MK+AzSd}wTvBEnDFKU?P1LUifG%wQMB){uD?f)!>yaTVgD}+_T=Mk1aIRh
zl&bOC+14&E@m@&TW8w*QZ=>&xGr#_(9;yhJg-_Z^bcWm!C<hr?I*8_r6k|Qg#JE+O
zEXFyC0tCe(cDdaYDBWd!)@#=vj_*UNWoq5Y336n%a1IVkG||U*(v0F({90(hQSF5w
zt`0+;GVx=JNmPbi^V&igKf;x%%jN@foO%M2<IY5}w;A{;w{3JCm*Yf}tH!?;qI)Kn
z7nEi{I<wL=dG(Awn2h(#?@_{+>$q_Gq7MT=;{ery%7)O%0-}JFLwCpO85ib*SW4BM
ze9KgHil5vV#Kw44KWnG`fqq%+ai!DAY5Y6Z$21vcG%Yw-*D96d|G@h!o^!a48y85I
zZ@_=a4B|)ZgXY|1kj44iyqOi||2*rypd<y2#>no6etqLaleu{>97vlk(GD1mbaF5~
zp#~jUVo+!z2%8}Wy)+VhjPh(<q8QjKV;AuilGZny7^Cq|OL&32hZOM!v`ahijFqp8
z&{gJ~+Wtn;5e1yd5iTB}V>?4I0*XLEG%VW*e*i5`ZbCMO>}KT-X=5Xp>#8YOO<+nd
zW~aKp-^t~$+#v&1QBSa&6{(jnu<z|tD_imQ?vM+ahm`jgS+7uQfl<=JGQ}`FL!dVR
zgsOr|G|xhwfZ{4iQKtrLWyOV)&KfcAEXEWxZ~KL@c|fDN?RCj8=_$x)AW1eo##OKG
zBOTT|a0xOQxxWdg{Y%@sIrk)VY*%D(#<sBtV(wp!JAsMV==FRZR-HHS{_vpBv!Rl^
z#ez5TEak61QWV);ntm+TJy-s9m{57csdG;e8d;-6%T0Nr#(6<R^MmpIacK7WYcv;1
zsi7CxecTW~bpnKkLv5=j4`M0RNiY14O|KKiO#n9uEl%KTllY@JPK^;oV3%`P1W14G
z0wU@y5{ksY)~lSP1_7;)XNIi5O(ewxetBmIfD(KHlNf+(4OQ~4ozMHV)`E_kEJ~Sc
zv^s6fy%b~U#%%f5rm00`qt!s7yHzpKlv3lttmd2q^a~(1wXMbKr&k<}K@Skgz6dfy
zUnM~t;C^2XKT{QjA~+8TQ$Yh|D`g_RLmDT$EgaOK5}RNv6$JQ<O+;^AlthhwM;&k5
zSb8naphWz-`#ExrA}8x3kJH|<P^1eO!_@?A4|8DNC#u+Lf4<7P=a+Z-z<unrd4(ze
z!gxgNwYXv5B_*R4L%1YKJX&q1#XTMbUqYI+zq1~kc$iXF)s*p&>$R`P%673@HU!Q3
zt+>zKuiJXr9)z%Oc`Igf<f@n_c5}o1B5(^o+9UIFR~x&y>L9)N25ln7X`$p(BQ%LS
zc-!jX(zZ3&84nD4E#6DD!$i#btO@6cE6!U&+IW?UwxK(%c*wTd?lF2;g{g11*ps>E
zy%8HxS<gpCMb|s^UfBIvodRxZliJ3QjON>6stx%3q>i@7{lva{-y!J86g25NkhUy#
z?}I=kis#IaU?o!pk)@kjiW8RGvTq$98^6lZ^ijg)FY2x>YD;KUtnaFi$VSJtKlhZn
z1s&->@=_G|+$d>|u<$Q$Ww=IPp6Lpk?vmO7_8LjrV-fL}3tRgV&`)(rHr}17ek=*O
z;E5(ED|2}L`Vz2z@)P&N0`8?YQFS=RQBSDE1xU-cJg}0g5}5%009dhqY>Oo6&2Y8J
zxx4X2RPUd9i%+^m<S4qDpw=yypG3K6j@W+%be2TN@2Vn~nAR2{DHU69%)YeG*&JA@
zx)+2g?adSe#1f{u`$N`$kH2FcL+fP63|)ez%7z46kyzV<cdy6*5^Me6WLGntZ+9;+
z1T|cEOvC!NprXHS5^xy@OQHcGp0fgo{QojgdfZ!3l>^vWvoy60@DCwy%JPgw^~noy
F{{wM8NgDtF

literal 0
HcmV?d00001

diff --git a/icon.svg b/icon.svg
deleted file mode 100644
index e80d60cd..00000000
--- a/icon.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
-<rect fill="#2C2C2C" width="128" height="128"/>
-<linearGradient id="path1948_1_" gradientUnits="userSpaceOnUse" x1="93.2342" y1="37.3458" x2="202.2505" y2="-56.4481" gradientTransform="matrix(0.5625 0 0 -0.568 -46.5838 31.8087)">
-	<stop  offset="0" style="stop-color:#5C9FD3"/>
-	<stop  offset="1" style="stop-color:#316A99"/>
-</linearGradient>
-<path id="path1948" fill="url(#path1948_1_)" d="M63.5,7.4c-4.6,0-9,0.4-12.8,1.1c-11.3,2-13.4,6.2-13.4,13.9v10.2h26.8v3.4H37.3
-	H27.2c-7.8,0-14.6,4.7-16.8,13.6c-2.5,10.2-2.6,16.6,0,27.2c1.9,7.9,6.5,13.6,14.3,13.6h9.2V78.2c0-8.8,7.7-16.7,16.8-16.7h26.8
-	c7.5,0,13.4-6.1,13.4-13.6V22.4c0-7.3-6.1-12.7-13.4-13.9C72.9,7.7,68.1,7.4,63.5,7.4z M49,15.6c2.8,0,5,2.3,5,5.1
-	c0,2.8-2.3,5.1-5,5.1c-2.8,0-5-2.3-5-5.1C44,17.9,46.2,15.6,49,15.6z"/>
-<linearGradient id="path1950_1_" gradientUnits="userSpaceOnUse" x1="244.397" y1="-113.2161" x2="205.4673" y2="-58.1373" gradientTransform="matrix(0.5625 0 0 -0.568 -46.5838 31.8087)">
-	<stop  offset="0" style="stop-color:#FFD43D"/>
-	<stop  offset="1" style="stop-color:#FEE875"/>
-</linearGradient>
-<path id="path1950" fill="url(#path1950_1_)" d="M94.2,36.1V48c0,9.2-7.8,17-16.8,17H50.7c-7.3,0-13.4,6.3-13.4,13.6v25.5
-	c0,7.3,6.3,11.5,13.4,13.6c8.5,2.5,16.6,2.9,26.8,0c6.8-2,13.4-5.9,13.4-13.6V93.9H64.1v-3.4h26.8h13.4c7.8,0,10.7-5.4,13.4-13.6
-	c2.8-8.4,2.7-16.5,0-27.2c-1.9-7.8-5.6-13.6-13.4-13.6H94.2z M79.2,100.7c2.8,0,5,2.3,5,5.1c0,2.8-2.3,5.1-5,5.1c-2.8,0-5-2.3-5-5.1
-	C74.1,103,76.4,100.7,79.2,100.7z"/>
-</svg>
diff --git a/package.json b/package.json
index b7b86461..759d184b 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,7 @@
     "syntax",
     "python3"
   ],
-  "icon": "icon.svg",
+  "icon": "icon.png",
   "galleryBanner": {
     "color": "#2c2c2c",
     "theme": "dark"

From 361a4964a559481330764a447e7bab88d4f1b01b Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor.petrovykh@gmail.com>
Date: Thu, 10 Aug 2017 20:04:22 -0400
Subject: [PATCH 29/65] Clean-up the grammar so that MagicRegExp does not have
 missing rules. (#100)

Thanks to @stoivo for noticing this issue.
---
 grammars/MagicPython.cson                  | 46 +++++-----
 grammars/MagicPython.tmLanguage            | 98 +++++++++++-----------
 grammars/MagicRegExp.cson                  | 23 +++++
 grammars/MagicRegExp.tmLanguage            | 49 +++++++++++
 grammars/src/MagicPython.syntax.yaml       | 16 ----
 grammars/src/regexp-common.inc.syntax.yaml | 16 ++++
 test/atom-spec/python-re-spec.js           | 17 ++++
 test/regexp/comments3.re                   | 10 +++
 8 files changed, 187 insertions(+), 88 deletions(-)
 create mode 100644 test/regexp/comments3.re

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index efdd9583..568d9944 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -252,11 +252,6 @@ repository:
     captures:
       "1":
         name: "keyword.control.flow.python"
-  codetags:
-    match: "(?:\\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\\b)"
-    captures:
-      "1":
-        name: "keyword.codetag.notation.python"
   "statement-keyword":
     patterns: [
       {
@@ -988,24 +983,6 @@ repository:
         include: "#fstring-formatting-singe-brace"
       }
     ]
-  "fstring-formatting-braces":
-    patterns: [
-      {
-        comment: "empty braces are illegal"
-        match: "({)(\\s*?)(})"
-        captures:
-          "1":
-            name: "constant.character.format.placeholder.other.python"
-          "2":
-            name: "invalid.illegal.brace.python"
-          "3":
-            name: "constant.character.format.placeholder.other.python"
-      }
-      {
-        name: "constant.character.escape.python"
-        match: "({{|}})"
-      }
-    ]
   "fstring-formatting-singe-brace":
     name: "invalid.illegal.brace.python"
     match: "(}(?!}))"
@@ -1931,6 +1908,24 @@ repository:
         include: "#regexp-base-common"
       }
     ]
+  "fstring-formatting-braces":
+    patterns: [
+      {
+        comment: "empty braces are illegal"
+        match: "({)(\\s*?)(})"
+        captures:
+          "1":
+            name: "constant.character.format.placeholder.other.python"
+          "2":
+            name: "invalid.illegal.brace.python"
+          "3":
+            name: "constant.character.format.placeholder.other.python"
+      }
+      {
+        name: "constant.character.escape.python"
+        match: "({{|}})"
+      }
+    ]
   "regexp-base-common":
     patterns: [
       {
@@ -2066,6 +2061,11 @@ repository:
         include: "#regexp-escape-catchall"
       }
     ]
+  codetags:
+    match: "(?:\\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\\b)"
+    captures:
+      "1":
+        name: "keyword.codetag.notation.python"
   "comments-base":
     name: "comment.line.number-sign.python"
     begin: "(\\#)"
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 7291caf0..6545fbab 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -404,19 +404,6 @@
           </dict>
         </dict>
       </dict>
-      <key>codetags</key>
-      <dict>
-        <key>match</key>
-        <string>(?:\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\b)</string>
-        <key>captures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.codetag.notation.python</string>
-          </dict>
-        </dict>
-      </dict>
       <key>statement-keyword</key>
       <dict>
         <key>patterns</key>
@@ -1509,42 +1496,6 @@
           </dict>
         </array>
       </dict>
-      <key>fstring-formatting-braces</key>
-      <dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>comment</key>
-            <string>empty braces are illegal</string>
-            <key>match</key>
-            <string>({)(\s*?)(})</string>
-            <key>captures</key>
-            <dict>
-              <key>1</key>
-              <dict>
-                <key>name</key>
-                <string>constant.character.format.placeholder.other.python</string>
-              </dict>
-              <key>2</key>
-              <dict>
-                <key>name</key>
-                <string>invalid.illegal.brace.python</string>
-              </dict>
-              <key>3</key>
-              <dict>
-                <key>name</key>
-                <string>constant.character.format.placeholder.other.python</string>
-              </dict>
-            </dict>
-          </dict>
-          <dict>
-            <key>name</key>
-            <string>constant.character.escape.python</string>
-            <key>match</key>
-            <string>({{|}})</string>
-          </dict>
-        </array>
-      </dict>
       <key>fstring-formatting-singe-brace</key>
       <dict>
         <key>name</key>
@@ -2978,6 +2929,42 @@ indirectly through syntactic constructs
           </dict>
         </array>
       </dict>
+      <key>fstring-formatting-braces</key>
+      <dict>
+        <key>patterns</key>
+        <array>
+          <dict>
+            <key>comment</key>
+            <string>empty braces are illegal</string>
+            <key>match</key>
+            <string>({)(\s*?)(})</string>
+            <key>captures</key>
+            <dict>
+              <key>1</key>
+              <dict>
+                <key>name</key>
+                <string>constant.character.format.placeholder.other.python</string>
+              </dict>
+              <key>2</key>
+              <dict>
+                <key>name</key>
+                <string>invalid.illegal.brace.python</string>
+              </dict>
+              <key>3</key>
+              <dict>
+                <key>name</key>
+                <string>constant.character.format.placeholder.other.python</string>
+              </dict>
+            </dict>
+          </dict>
+          <dict>
+            <key>name</key>
+            <string>constant.character.escape.python</string>
+            <key>match</key>
+            <string>({{|}})</string>
+          </dict>
+        </array>
+      </dict>
       <key>regexp-base-common</key>
       <dict>
         <key>patterns</key>
@@ -3188,6 +3175,19 @@ indirectly through syntactic constructs
           </dict>
         </array>
       </dict>
+      <key>codetags</key>
+      <dict>
+        <key>match</key>
+        <string>(?:\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\b)</string>
+        <key>captures</key>
+        <dict>
+          <key>1</key>
+          <dict>
+            <key>name</key>
+            <string>keyword.codetag.notation.python</string>
+          </dict>
+        </dict>
+      </dict>
       <key>comments-base</key>
       <dict>
         <key>name</key>
diff --git a/grammars/MagicRegExp.cson b/grammars/MagicRegExp.cson
index 69e0c300..175b80f6 100644
--- a/grammars/MagicRegExp.cson
+++ b/grammars/MagicRegExp.cson
@@ -35,6 +35,24 @@ repository:
         include: "#regexp-base-common"
       }
     ]
+  "fstring-formatting-braces":
+    patterns: [
+      {
+        comment: "empty braces are illegal"
+        match: "({)(\\s*?)(})"
+        captures:
+          "1":
+            name: "constant.character.format.placeholder.other.python"
+          "2":
+            name: "invalid.illegal.brace.python"
+          "3":
+            name: "constant.character.format.placeholder.other.python"
+      }
+      {
+        name: "constant.character.escape.python"
+        match: "({{|}})"
+      }
+    ]
   "regexp-base-common":
     patterns: [
       {
@@ -170,6 +188,11 @@ repository:
         include: "#regexp-escape-catchall"
       }
     ]
+  codetags:
+    match: "(?:\\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\\b)"
+    captures:
+      "1":
+        name: "keyword.codetag.notation.python"
   "regexp-expression":
     patterns: [
       {
diff --git a/grammars/MagicRegExp.tmLanguage b/grammars/MagicRegExp.tmLanguage
index 3bc9d48e..3d19e058 100644
--- a/grammars/MagicRegExp.tmLanguage
+++ b/grammars/MagicRegExp.tmLanguage
@@ -58,6 +58,42 @@
           </dict>
         </array>
       </dict>
+      <key>fstring-formatting-braces</key>
+      <dict>
+        <key>patterns</key>
+        <array>
+          <dict>
+            <key>comment</key>
+            <string>empty braces are illegal</string>
+            <key>match</key>
+            <string>({)(\s*?)(})</string>
+            <key>captures</key>
+            <dict>
+              <key>1</key>
+              <dict>
+                <key>name</key>
+                <string>constant.character.format.placeholder.other.python</string>
+              </dict>
+              <key>2</key>
+              <dict>
+                <key>name</key>
+                <string>invalid.illegal.brace.python</string>
+              </dict>
+              <key>3</key>
+              <dict>
+                <key>name</key>
+                <string>constant.character.format.placeholder.other.python</string>
+              </dict>
+            </dict>
+          </dict>
+          <dict>
+            <key>name</key>
+            <string>constant.character.escape.python</string>
+            <key>match</key>
+            <string>({{|}})</string>
+          </dict>
+        </array>
+      </dict>
       <key>regexp-base-common</key>
       <dict>
         <key>patterns</key>
@@ -268,6 +304,19 @@
           </dict>
         </array>
       </dict>
+      <key>codetags</key>
+      <dict>
+        <key>match</key>
+        <string>(?:\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\b)</string>
+        <key>captures</key>
+        <dict>
+          <key>1</key>
+          <dict>
+            <key>name</key>
+            <string>keyword.codetag.notation.python</string>
+          </dict>
+        </dict>
+      </dict>
       <key>regexp-expression</key>
       <dict>
         <key>patterns</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index f39918b8..2c31e243 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -351,11 +351,6 @@ repository:
     captures:
       '1': {name: keyword.control.flow.python}
 
-  codetags:
-    match: (?:\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\b)
-    captures:
-      '1': {name: keyword.codetag.notation.python}
-
   statement-keyword:
     patterns:
       - name: storage.type.function.python
@@ -824,17 +819,6 @@ repository:
       - include: '#fstring-formatting-braces'
       - include: '#fstring-formatting-singe-brace'
 
-  fstring-formatting-braces:
-    patterns:
-      - comment: empty braces are illegal
-        match: ({)(\s*?)(})
-        captures:
-          '1': {name: constant.character.format.placeholder.other.python}
-          '2': {name: invalid.illegal.brace.python}
-          '3': {name: constant.character.format.placeholder.other.python}
-      - name: constant.character.escape.python
-        match: ({{|}})
-
   fstring-formatting-singe-brace:
     name: invalid.illegal.brace.python
     match: (}(?!}))
diff --git a/grammars/src/regexp-common.inc.syntax.yaml b/grammars/src/regexp-common.inc.syntax.yaml
index d7b02061..e367af87 100644
--- a/grammars/src/regexp-common.inc.syntax.yaml
+++ b/grammars/src/regexp-common.inc.syntax.yaml
@@ -12,6 +12,17 @@ repository:
       - match: \{.*?\}
       - include: '#regexp-base-common'
 
+  fstring-formatting-braces:
+    patterns:
+      - comment: empty braces are illegal
+        match: ({)(\s*?)(})
+        captures:
+          '1': {name: constant.character.format.placeholder.other.python}
+          '2': {name: invalid.illegal.brace.python}
+          '3': {name: constant.character.format.placeholder.other.python}
+      - name: constant.character.escape.python
+        match: ({{|}})
+
   regexp-base-common:
     patterns:
       - name: support.other.match.any.regexp
@@ -109,4 +120,9 @@ repository:
       - include: '#regexp-escape-character'
       - include: '#regexp-escape-unicode'
       - include: '#regexp-escape-catchall'
+
+  codetags:
+    match: (?:\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\b)
+    captures:
+      '1': {name: keyword.codetag.notation.python}
 ...
diff --git a/test/atom-spec/python-re-spec.js b/test/atom-spec/python-re-spec.js
index 5a5557c5..2874e777 100644
--- a/test/atom-spec/python-re-spec.js
+++ b/test/atom-spec/python-re-spec.js
@@ -56,6 +56,23 @@ describe("Grammar Tests", function() {
       expect(tokens[4][3].scopes).toEqual(["source.regexp.python","comment.regexp","punctuation.comment.end.regexp"]);
     });
 
+  it("test/regexp/comments3.re", 
+    function() {
+      tokens = grammar.tokenizeLines("foo(?#NOTE:comment)bar")
+      expect(tokens[0][0].value).toBe("foo");
+      expect(tokens[0][0].scopes).toEqual(["source.regexp.python"]);
+      expect(tokens[0][1].value).toBe("(?#");
+      expect(tokens[0][1].scopes).toEqual(["source.regexp.python","comment.regexp","punctuation.comment.begin.regexp"]);
+      expect(tokens[0][2].value).toBe("NOTE");
+      expect(tokens[0][2].scopes).toEqual(["source.regexp.python","comment.regexp","keyword.codetag.notation.python"]);
+      expect(tokens[0][3].value).toBe(":comment");
+      expect(tokens[0][3].scopes).toEqual(["source.regexp.python","comment.regexp"]);
+      expect(tokens[0][4].value).toBe(")");
+      expect(tokens[0][4].scopes).toEqual(["source.regexp.python","comment.regexp","punctuation.comment.end.regexp"]);
+      expect(tokens[0][5].value).toBe("bar");
+      expect(tokens[0][5].scopes).toEqual(["source.regexp.python"]);
+    });
+
   it("test/regexp/conditional1.re", 
     function() {
       tokens = grammar.tokenizeLines("(<)?(\\w+@\\w+(?:\\.\\w+)+)(?(1)>|$)")
diff --git a/test/regexp/comments3.re b/test/regexp/comments3.re
new file mode 100644
index 00000000..8f1cb962
--- /dev/null
+++ b/test/regexp/comments3.re
@@ -0,0 +1,10 @@
+foo(?#NOTE:comment)bar
+
+
+
+foo           : source.regexp.python
+(?#           : comment.regexp, punctuation.comment.begin.regexp, source.regexp.python
+NOTE          : comment.regexp, keyword.codetag.notation.python, source.regexp.python
+:comment      : comment.regexp, source.regexp.python
+)             : comment.regexp, punctuation.comment.end.regexp, source.regexp.python
+bar           : source.regexp.python

From dcb1a380a0a73e5905ae090696bc40fe1d8595ca Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor.petrovykh@gmail.com>
Date: Thu, 10 Aug 2017 20:04:38 -0400
Subject: [PATCH 30/65] Update README.md. (#99)

---
 README.md | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/README.md b/README.md
index dd281085..41a48420 100644
--- a/README.md
+++ b/README.md
@@ -3,24 +3,26 @@
 This is a package with preferences and syntax highlighter for cutting edge
 Python 3, although Python 2 is well supported, too.  The syntax is compatible
 with [Sublime Text](http://www.sublimetext.com), [Atom](http://atom.io) and
-[Visual Studio Code](http://code.visualstudio.com).
-It is meant to be a drop-in replacement for the default Python package.
+[Visual Studio Code](http://code.visualstudio.com). It is meant to be a drop-in
+replacement for the default Python package.
 
-MagicPython correctly highlights all Python 3.5 and 3.6 syntax features, 
-including type annotations, f-strings and regular expressions.  It is built
-from scratch for robustness with an extensive test suite.
+We are proud to say that MagicPython is used by GitHub to highlight Python.
 
-We are proud to say that MagicPython has been included into the
-[github/linguist](https://github.com/github/linguist), a library used
-by GitHub.com to process languages.
+**Attention VSCode users**: MagicPython is used as the _default_
+Python highlighter in Visual Studio Code. Don't install it unless you
+want or need the cutting edge version of it. You will likely see no
+difference because you're already using MagicPython.
 
+MagicPython correctly highlights all Python 3 syntax features,
+including type annotations, f-strings and regular expressions. It is
+built from scratch for robustness with an extensive test suite.
 
-![](https://magicstack.github.io/MagicPython/example.png)
-
-Type hints in comments require support by the color scheme.  The one
+Type hints in comments require support by the color scheme. The one
 used in the screenshot is
 [Chromodynamics](https://github.com/MagicStack/Chromodynamics).
 
+![](https://magicstack.github.io/MagicPython/example.png)
+
 
 ## Installation Instructions
 

From b453f26ed856c9b16a053517c41207e3a72cc7d5 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor.petrovykh@gmail.com>
Date: Thu, 10 Aug 2017 22:35:17 -0400
Subject: [PATCH 31/65] Highlight `.` in its own scope. (#101)

The scope for `.` is `punctuation.separator.period.python`.
---
 grammars/MagicPython.cson            |  14 +-
 grammars/MagicPython.tmLanguage      |  27 +-
 grammars/src/MagicPython.syntax.yaml |  11 +-
 misc/scopes                          |   1 +
 test/atom-spec/python-spec.js        | 562 +++++++++++++++------------
 test/builtins/builtins3.py           |  78 ++--
 test/builtins/builtins4.py           |  12 +-
 test/builtins/builtins5.py           |   9 +-
 test/calls/call3.py                  |   6 +-
 test/calls/call4.py                  |   8 +-
 test/calls/call7.py                  |  10 +-
 test/calls/call8.py                  |  12 +-
 test/calls/print1.py                 |   4 +-
 test/classes/class11.py              |  10 +-
 test/classes/class12.py              |  10 +-
 test/classes/class14.py              |   6 +-
 test/classes/class2.py               |   4 +-
 test/classes/super1.py               |  10 +-
 test/expressions/const1.py           |   8 +-
 test/expressions/expr10.py           |   2 +-
 test/expressions/expr11.py           |   2 +-
 test/expressions/expr15.py           |   2 +-
 test/expressions/expr18.py           |   4 +-
 test/expressions/expr19.py           |  18 +-
 test/expressions/expr7.py            |   6 +-
 test/fstrings/comment4.py            |   2 +-
 test/fstrings/simple2.py             |   2 +-
 test/illegals/illegal1.py            |   2 +-
 test/regexp/python8.py               |   4 +-
 test/statements/import1.py           |   3 +-
 test/statements/import2.py           |  12 +-
 test/statements/import3.py           |   8 +-
 test/statements/import4.py           |   8 +-
 test/statements/import5.py           |   6 +-
 test/strings/format2.py              |   2 +-
 35 files changed, 493 insertions(+), 392 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 568d9944..526b2873 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -386,7 +386,7 @@ repository:
       }
     ]
   "member-access":
-    begin: "\\.\\s*(?!\\.)"
+    begin: "(\\.)\\s*(?!\\.)"
     end: '''
       (?x)
         # stop when you've just read non-whitespace followed by non-word
@@ -398,6 +398,9 @@ repository:
         $
       
     '''
+    beginCaptures:
+      "1":
+        name: "punctuation.separator.period.python"
     patterns: [
       {
         include: "#function-call"
@@ -995,12 +998,14 @@ repository:
       {
         match: '''
           (?x)
-            \\s* \\b(from)\\b (\\s*\\.+\\s*) (import)?
+            \\s* \\b(from)\\b \\s*(\\.+)\\s* (import)?
           
         '''
         captures:
           "1":
             name: "keyword.control.import.python"
+          "2":
+            name: "punctuation.separator.period.python"
           "3":
             name: "keyword.control.import.python"
       }
@@ -1122,8 +1127,11 @@ repository:
       "1":
         name: "entity.other.inherited-class.python"
   "member-access-class":
-    begin: "\\.\\s*(?!\\.)"
+    begin: "(\\.)\\s*(?!\\.)"
     end: "(?<=\\S)(?=\\W)|$"
+    beginCaptures:
+      "1":
+        name: "punctuation.separator.period.python"
     patterns: [
       {
         include: "#call-wrapper-inheritance"
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 6545fbab..ae03ed0e 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -589,7 +589,7 @@
       <key>member-access</key>
       <dict>
         <key>begin</key>
-        <string>\.\s*(?!\.)</string>
+        <string>(\.)\s*(?!\.)</string>
         <key>end</key>
         <string>(?x)
   # stop when you've just read non-whitespace followed by non-word
@@ -600,6 +600,14 @@
   (^|(?&lt;=\s))(?=[^\\\w\s]) |
   $
 </string>
+        <key>beginCaptures</key>
+        <dict>
+          <key>1</key>
+          <dict>
+            <key>name</key>
+            <string>punctuation.separator.period.python</string>
+          </dict>
+        </dict>
         <key>patterns</key>
         <array>
           <dict>
@@ -1513,7 +1521,7 @@
           <dict>
             <key>match</key>
             <string>(?x)
-  \s* \b(from)\b (\s*\.+\s*) (import)?
+  \s* \b(from)\b \s*(\.+)\s* (import)?
 </string>
             <key>captures</key>
             <dict>
@@ -1522,6 +1530,11 @@
                 <key>name</key>
                 <string>keyword.control.import.python</string>
               </dict>
+              <key>2</key>
+              <dict>
+                <key>name</key>
+                <string>punctuation.separator.period.python</string>
+              </dict>
               <key>3</key>
               <dict>
                 <key>name</key>
@@ -1719,9 +1732,17 @@
       <key>member-access-class</key>
       <dict>
         <key>begin</key>
-        <string>\.\s*(?!\.)</string>
+        <string>(\.)\s*(?!\.)</string>
         <key>end</key>
         <string>(?&lt;=\S)(?=\W)|$</string>
+        <key>beginCaptures</key>
+        <dict>
+          <key>1</key>
+          <dict>
+            <key>name</key>
+            <string>punctuation.separator.period.python</string>
+          </dict>
+        </dict>
         <key>patterns</key>
         <array>
           <dict>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 2c31e243..43009579 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -415,7 +415,7 @@ repository:
         match: (?x) \b ([[:alpha:]_]\w*) \b
 
   member-access:
-    begin: \.\s*(?!\.)
+    begin: (\.)\s*(?!\.)
     end: |
       (?x)
         # stop when you've just read non-whitespace followed by non-word
@@ -425,6 +425,8 @@ repository:
         # i.e. when seeing a non-identifier
         (^|(?<=\s))(?=[^\\\w\s]) |
         $
+    beginCaptures:
+      '1': {name: punctuation.separator.period.python}
     patterns:
       - include: '#function-call'
       - include: '#member-access-base'
@@ -829,9 +831,10 @@ repository:
     patterns:
       - match: |
           (?x)
-            \s* \b(from)\b (\s*\.+\s*) (import)?
+            \s* \b(from)\b \s*(\.+)\s* (import)?
         captures:
           '1': {name: keyword.control.import.python}
+          '2': {name: punctuation.separator.period.python}
           '3': {name: keyword.control.import.python}
       - name: keyword.control.import.python
         match: \b(?<!\.)import\b
@@ -907,8 +910,10 @@ repository:
       '1': {name: entity.other.inherited-class.python}
 
   member-access-class:
-    begin: \.\s*(?!\.)
+    begin: (\.)\s*(?!\.)
     end: (?<=\S)(?=\W)|$
+    beginCaptures:
+      '1': {name: punctuation.separator.period.python}
     patterns:
       - include: '#call-wrapper-inheritance'
       - include: '#member-access-base'
diff --git a/misc/scopes b/misc/scopes
index 72e0d629..128a673c 100644
--- a/misc/scopes
+++ b/misc/scopes
@@ -120,6 +120,7 @@ punctuation.separator.dict.python
 punctuation.separator.element.python
 punctuation.separator.inheritance.python
 punctuation.separator.parameters.python
+punctuation.separator.period.python
 punctuation.separator.slice.python
 storage.modifier.declaration.python
 storage.modifier.flag.regexp
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 0359e613..c0d65218 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -162,13 +162,13 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].value).toBe("some");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("__bases__");
       expect(tokens[1][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[2][0].value).toBe("some");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
-      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("__class__");
       expect(tokens[2][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[3][0].value).toBe("assert");
@@ -182,7 +182,7 @@ describe("Grammar Tests", function() {
       expect(tokens[5][0].value).toBe("__builtins__");
       expect(tokens[5][0].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[5][1].value).toBe(".");
-      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[5][2].value).toBe("len");
       expect(tokens[5][2].scopes).toEqual(["source.python"]);
       expect(tokens[6][0].value).toBe("print");
@@ -196,217 +196,217 @@ describe("Grammar Tests", function() {
       expect(tokens[7][0].value).toBe("some");
       expect(tokens[7][0].scopes).toEqual(["source.python"]);
       expect(tokens[7][1].value).toBe(".");
-      expect(tokens[7][1].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[7][2].value).toBe("__dict__");
       expect(tokens[7][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[8][0].value).toBe("some");
       expect(tokens[8][0].scopes).toEqual(["source.python"]);
       expect(tokens[8][1].value).toBe(".");
-      expect(tokens[8][1].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[8][2].value).toBe("__doc__");
       expect(tokens[8][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[9][0].value).toBe("some");
       expect(tokens[9][0].scopes).toEqual(["source.python"]);
       expect(tokens[9][1].value).toBe(".");
-      expect(tokens[9][1].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[9][2].value).toBe("__file__");
       expect(tokens[9][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[10][0].value).toBe("some");
       expect(tokens[10][0].scopes).toEqual(["source.python"]);
       expect(tokens[10][1].value).toBe(".");
-      expect(tokens[10][1].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[10][2].value).toBe("__members__");
       expect(tokens[10][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[11][0].value).toBe("some");
       expect(tokens[11][0].scopes).toEqual(["source.python"]);
       expect(tokens[11][1].value).toBe(".");
-      expect(tokens[11][1].scopes).toEqual(["source.python"]);
+      expect(tokens[11][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[11][2].value).toBe("__metaclass__");
       expect(tokens[11][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[12][0].value).toBe("some");
       expect(tokens[12][0].scopes).toEqual(["source.python"]);
       expect(tokens[12][1].value).toBe(".");
-      expect(tokens[12][1].scopes).toEqual(["source.python"]);
+      expect(tokens[12][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[12][2].value).toBe("__methods__");
       expect(tokens[12][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[13][0].value).toBe("some");
       expect(tokens[13][0].scopes).toEqual(["source.python"]);
       expect(tokens[13][1].value).toBe(".");
-      expect(tokens[13][1].scopes).toEqual(["source.python"]);
+      expect(tokens[13][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[13][2].value).toBe("__module__");
       expect(tokens[13][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[14][0].value).toBe("some");
       expect(tokens[14][0].scopes).toEqual(["source.python"]);
       expect(tokens[14][1].value).toBe(".");
-      expect(tokens[14][1].scopes).toEqual(["source.python"]);
+      expect(tokens[14][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[14][2].value).toBe("__mro__");
       expect(tokens[14][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[15][0].value).toBe("some");
       expect(tokens[15][0].scopes).toEqual(["source.python"]);
       expect(tokens[15][1].value).toBe(".");
-      expect(tokens[15][1].scopes).toEqual(["source.python"]);
+      expect(tokens[15][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[15][2].value).toBe("__name__");
       expect(tokens[15][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[16][0].value).toBe("some");
       expect(tokens[16][0].scopes).toEqual(["source.python"]);
       expect(tokens[16][1].value).toBe(".");
-      expect(tokens[16][1].scopes).toEqual(["source.python"]);
+      expect(tokens[16][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[16][2].value).toBe("__slots__");
       expect(tokens[16][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[17][0].value).toBe("some");
       expect(tokens[17][0].scopes).toEqual(["source.python"]);
       expect(tokens[17][1].value).toBe(".");
-      expect(tokens[17][1].scopes).toEqual(["source.python"]);
+      expect(tokens[17][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[17][2].value).toBe("__subclasses__");
       expect(tokens[17][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[18][0].value).toBe("some");
       expect(tokens[18][0].scopes).toEqual(["source.python"]);
       expect(tokens[18][1].value).toBe(".");
-      expect(tokens[18][1].scopes).toEqual(["source.python"]);
+      expect(tokens[18][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[18][2].value).toBe("__version__");
       expect(tokens[18][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[19][0].value).toBe("some");
       expect(tokens[19][0].scopes).toEqual(["source.python"]);
       expect(tokens[19][1].value).toBe(".");
-      expect(tokens[19][1].scopes).toEqual(["source.python"]);
+      expect(tokens[19][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[19][2].value).toBe("__weakref__");
       expect(tokens[19][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[20][0].value).toBe("some");
       expect(tokens[20][0].scopes).toEqual(["source.python"]);
       expect(tokens[20][1].value).toBe(".");
-      expect(tokens[20][1].scopes).toEqual(["source.python"]);
+      expect(tokens[20][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[20][2].value).toBe("__qualname__");
       expect(tokens[20][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[21][0].value).toBe("some");
       expect(tokens[21][0].scopes).toEqual(["source.python"]);
       expect(tokens[21][1].value).toBe(".");
-      expect(tokens[21][1].scopes).toEqual(["source.python"]);
+      expect(tokens[21][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[21][2].value).toBe("__code__");
       expect(tokens[21][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[22][0].value).toBe("some");
       expect(tokens[22][0].scopes).toEqual(["source.python"]);
       expect(tokens[22][1].value).toBe(".");
-      expect(tokens[22][1].scopes).toEqual(["source.python"]);
+      expect(tokens[22][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[22][2].value).toBe("__wrapped__");
       expect(tokens[22][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[23][0].value).toBe("some");
       expect(tokens[23][0].scopes).toEqual(["source.python"]);
       expect(tokens[23][1].value).toBe(".");
-      expect(tokens[23][1].scopes).toEqual(["source.python"]);
+      expect(tokens[23][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[23][2].value).toBe("__signature__");
       expect(tokens[23][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[24][0].value).toBe("some");
       expect(tokens[24][0].scopes).toEqual(["source.python"]);
       expect(tokens[24][1].value).toBe(".");
-      expect(tokens[24][1].scopes).toEqual(["source.python"]);
+      expect(tokens[24][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[24][2].value).toBe("__defaults__");
       expect(tokens[24][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[25][0].value).toBe("some");
       expect(tokens[25][0].scopes).toEqual(["source.python"]);
       expect(tokens[25][1].value).toBe(".");
-      expect(tokens[25][1].scopes).toEqual(["source.python"]);
+      expect(tokens[25][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[25][2].value).toBe("__func__");
       expect(tokens[25][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[26][0].value).toBe("some");
       expect(tokens[26][0].scopes).toEqual(["source.python"]);
       expect(tokens[26][1].value).toBe(".");
-      expect(tokens[26][1].scopes).toEqual(["source.python"]);
+      expect(tokens[26][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[26][2].value).toBe("__self__");
       expect(tokens[26][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[27][0].value).toBe("some");
       expect(tokens[27][0].scopes).toEqual(["source.python"]);
       expect(tokens[27][1].value).toBe(".");
-      expect(tokens[27][1].scopes).toEqual(["source.python"]);
+      expect(tokens[27][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[27][2].value).toBe("__kwdefaults__");
       expect(tokens[27][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[28][0].value).toBe("some");
       expect(tokens[28][0].scopes).toEqual(["source.python"]);
       expect(tokens[28][1].value).toBe(".");
-      expect(tokens[28][1].scopes).toEqual(["source.python"]);
+      expect(tokens[28][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[28][2].value).toBe("__matmul__");
       expect(tokens[28][2].scopes).toEqual(["source.python","support.function.magic.python"]);
       expect(tokens[29][0].value).toBe("some");
       expect(tokens[29][0].scopes).toEqual(["source.python"]);
       expect(tokens[29][1].value).toBe(".");
-      expect(tokens[29][1].scopes).toEqual(["source.python"]);
+      expect(tokens[29][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[29][2].value).toBe("__imatmul__");
       expect(tokens[29][2].scopes).toEqual(["source.python","support.function.magic.python"]);
       expect(tokens[30][0].value).toBe("some");
       expect(tokens[30][0].scopes).toEqual(["source.python"]);
       expect(tokens[30][1].value).toBe(".");
-      expect(tokens[30][1].scopes).toEqual(["source.python"]);
+      expect(tokens[30][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[30][2].value).toBe("__rmatmul__");
       expect(tokens[30][2].scopes).toEqual(["source.python","support.function.magic.python"]);
       expect(tokens[31][0].value).toBe("some");
       expect(tokens[31][0].scopes).toEqual(["source.python"]);
       expect(tokens[31][1].value).toBe(".");
-      expect(tokens[31][1].scopes).toEqual(["source.python"]);
+      expect(tokens[31][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[31][2].value).toBe("__annotations__");
       expect(tokens[31][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[32][0].value).toBe("some");
       expect(tokens[32][0].scopes).toEqual(["source.python"]);
       expect(tokens[32][1].value).toBe(".");
-      expect(tokens[32][1].scopes).toEqual(["source.python"]);
+      expect(tokens[32][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[32][2].value).toBe("__init_subclass__");
       expect(tokens[32][2].scopes).toEqual(["source.python","support.function.magic.python"]);
       expect(tokens[33][0].value).toBe("some");
       expect(tokens[33][0].scopes).toEqual(["source.python"]);
       expect(tokens[33][1].value).toBe(".");
-      expect(tokens[33][1].scopes).toEqual(["source.python"]);
+      expect(tokens[33][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[33][2].value).toBe("__set_name__");
       expect(tokens[33][2].scopes).toEqual(["source.python","support.function.magic.python"]);
       expect(tokens[34][0].value).toBe("some");
       expect(tokens[34][0].scopes).toEqual(["source.python"]);
       expect(tokens[34][1].value).toBe(".");
-      expect(tokens[34][1].scopes).toEqual(["source.python"]);
+      expect(tokens[34][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[34][2].value).toBe("__fspath__");
       expect(tokens[34][2].scopes).toEqual(["source.python","support.function.magic.python"]);
       expect(tokens[35][0].value).toBe("some");
       expect(tokens[35][0].scopes).toEqual(["source.python"]);
       expect(tokens[35][1].value).toBe(".");
-      expect(tokens[35][1].scopes).toEqual(["source.python"]);
+      expect(tokens[35][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[35][2].value).toBe("__classcell__");
       expect(tokens[35][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[36][0].value).toBe("some");
       expect(tokens[36][0].scopes).toEqual(["source.python"]);
       expect(tokens[36][1].value).toBe(".");
-      expect(tokens[36][1].scopes).toEqual(["source.python"]);
+      expect(tokens[36][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[36][2].value).toBe("__bytes__");
       expect(tokens[36][2].scopes).toEqual(["source.python","support.function.magic.python"]);
       expect(tokens[37][0].value).toBe("some");
       expect(tokens[37][0].scopes).toEqual(["source.python"]);
       expect(tokens[37][1].value).toBe(".");
-      expect(tokens[37][1].scopes).toEqual(["source.python"]);
+      expect(tokens[37][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[37][2].value).toBe("__spec__");
       expect(tokens[37][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[38][0].value).toBe("some");
       expect(tokens[38][0].scopes).toEqual(["source.python"]);
       expect(tokens[38][1].value).toBe(".");
-      expect(tokens[38][1].scopes).toEqual(["source.python"]);
+      expect(tokens[38][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[38][2].value).toBe("__path__");
       expect(tokens[38][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[39][0].value).toBe("some");
       expect(tokens[39][0].scopes).toEqual(["source.python"]);
       expect(tokens[39][1].value).toBe(".");
-      expect(tokens[39][1].scopes).toEqual(["source.python"]);
+      expect(tokens[39][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[39][2].value).toBe("__prepare__");
       expect(tokens[39][2].scopes).toEqual(["source.python","support.function.magic.python"]);
       expect(tokens[40][0].value).toBe("some");
       expect(tokens[40][0].scopes).toEqual(["source.python"]);
       expect(tokens[40][1].value).toBe(".");
-      expect(tokens[40][1].scopes).toEqual(["source.python"]);
+      expect(tokens[40][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[40][2].value).toBe("__package__");
       expect(tokens[40][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[41][0].value).toBe("some");
       expect(tokens[41][0].scopes).toEqual(["source.python"]);
       expect(tokens[41][1].value).toBe(".");
-      expect(tokens[41][1].scopes).toEqual(["source.python"]);
+      expect(tokens[41][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[41][2].value).toBe("__traceback__");
       expect(tokens[41][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[42][0].value).toBe("some");
       expect(tokens[42][0].scopes).toEqual(["source.python"]);
       expect(tokens[42][1].value).toBe(".");
-      expect(tokens[42][1].scopes).toEqual(["source.python"]);
+      expect(tokens[42][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[42][2].value).toBe("__notspecial__");
       expect(tokens[42][2].scopes).toEqual(["source.python"]);
     });
@@ -417,37 +417,37 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("some");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("int");
       expect(tokens[0][2].scopes).toEqual(["source.python"]);
       expect(tokens[1][0].value).toBe("some");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("sum");
       expect(tokens[1][2].scopes).toEqual(["source.python"]);
       expect(tokens[2][0].value).toBe("some");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
-      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("super");
       expect(tokens[2][2].scopes).toEqual(["source.python"]);
       expect(tokens[3][0].value).toBe("some");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("unicode");
       expect(tokens[3][2].scopes).toEqual(["source.python"]);
       expect(tokens[4][0].value).toBe("some");
       expect(tokens[4][0].scopes).toEqual(["source.python"]);
       expect(tokens[4][1].value).toBe(".");
-      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[4][2].value).toBe("foo");
       expect(tokens[4][2].scopes).toEqual(["source.python"]);
       expect(tokens[5][0].value).toBe("some");
       expect(tokens[5][0].scopes).toEqual(["source.python"]);
       expect(tokens[5][1].value).toBe(".");
-      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[5][2].value).toBe("Exception");
       expect(tokens[5][2].scopes).toEqual(["source.python"]);
     });
@@ -457,18 +457,22 @@ describe("Grammar Tests", function() {
       tokens = grammar.tokenizeLines("some. True\nsome. \\\n    True\nTrue\nsome.\n    True")
       expect(tokens[0][0].value).toBe("some");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
-      expect(tokens[0][1].value).toBe(". ");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
-      expect(tokens[0][2].value).toBe("True");
-      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][2].value).toBe(" ");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe("True");
+      expect(tokens[0][3].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
       expect(tokens[1][0].value).toBe("some");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
-      expect(tokens[1][1].value).toBe(". ");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
-      expect(tokens[1][2].value).toBe("\\");
-      expect(tokens[1][2].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
-      expect(tokens[1][3].value).toBe("");
-      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(".");
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("\\");
+      expect(tokens[1][3].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][4].value).toBe("");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
       expect(tokens[2][0].value).toBe("    ");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe("True");
@@ -478,7 +482,9 @@ describe("Grammar Tests", function() {
       expect(tokens[4][0].value).toBe("some");
       expect(tokens[4][0].scopes).toEqual(["source.python"]);
       expect(tokens[4][1].value).toBe(".");
-      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[4][2].value).toBe("");
+      expect(tokens[4][2].scopes).toEqual(["source.python"]);
       expect(tokens[5][0].value).toBe("    ");
       expect(tokens[5][0].scopes).toEqual(["source.python"]);
       expect(tokens[5][1].value).toBe("True");
@@ -583,7 +589,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("foo");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("class");
       expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","keyword.control.flow.python"]);
       expect(tokens[0][3].value).toBe("(");
@@ -595,7 +601,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].value).toBe("foo");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("and");
       expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","keyword.control.flow.python"]);
       expect(tokens[1][3].value).toBe("(");
@@ -605,7 +611,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][0].value).toBe("foo");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
-      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("if");
       expect(tokens[2][2].scopes).toEqual(["source.python","keyword.control.flow.python"]);
     });
@@ -616,7 +622,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("foo");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("1");
       expect(tokens[0][2].scopes).toEqual(["source.python"]);
       expect(tokens[1][0].value).toBe("foo");
@@ -644,7 +650,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][0].value).toBe("foo");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
-      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("None");
       expect(tokens[2][2].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
       expect(tokens[2][3].value).toBe(" ");
@@ -656,11 +662,11 @@ describe("Grammar Tests", function() {
       expect(tokens[2][6].value).toBe("foo");
       expect(tokens[2][6].scopes).toEqual(["source.python"]);
       expect(tokens[2][7].value).toBe(".");
-      expect(tokens[2][7].scopes).toEqual(["source.python"]);
+      expect(tokens[2][7].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][8].value).toBe("None");
       expect(tokens[2][8].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
       expect(tokens[2][9].value).toBe(".");
-      expect(tokens[2][9].scopes).toEqual(["source.python"]);
+      expect(tokens[2][9].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][10].value).toBe("baz");
       expect(tokens[2][10].scopes).toEqual(["source.python"]);
     });
@@ -749,7 +755,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("foo");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("__class__");
       expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
       expect(tokens[0][3].value).toBe(" ");
@@ -767,7 +773,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].value).toBe("foo");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("__class__");
       expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
       expect(tokens[1][3].value).toBe("(");
@@ -783,7 +789,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][0].value).toBe("foo");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
-      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("__add__");
       expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[2][3].value).toBe(" ");
@@ -801,7 +807,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][0].value).toBe("foo");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("__add__");
       expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[3][3].value).toBe("(");
@@ -819,7 +825,7 @@ describe("Grammar Tests", function() {
       expect(tokens[5][0].value).toBe("foo");
       expect(tokens[5][0].scopes).toEqual(["source.python"]);
       expect(tokens[5][1].value).toBe(".");
-      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[5][2].value).toBe("__class__");
       expect(tokens[5][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[5][3].value).toBe(" ");
@@ -833,72 +839,80 @@ describe("Grammar Tests", function() {
       tokens = grammar.tokenizeLines("foo. __class__(foo=bar)\nfoo. __class__ (foo=bar)\nfoo. __add__ (foo=bar)\nfoo. __add__(foo=bar)")
       expect(tokens[0][0].value).toBe("foo");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
-      expect(tokens[0][1].value).toBe(". ");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
-      expect(tokens[0][2].value).toBe("__class__");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
-      expect(tokens[0][3].value).toBe("(");
-      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
-      expect(tokens[0][4].value).toBe("foo");
-      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
-      expect(tokens[0][5].value).toBe("=");
-      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
-      expect(tokens[0][6].value).toBe("bar");
-      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
-      expect(tokens[0][7].value).toBe(")");
-      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][2].value).toBe(" ");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe("__class__");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
+      expect(tokens[0][4].value).toBe("(");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][5].value).toBe("foo");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][6].value).toBe("=");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][7].value).toBe("bar");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][8].value).toBe(")");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[1][0].value).toBe("foo");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
-      expect(tokens[1][1].value).toBe(". ");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
-      expect(tokens[1][2].value).toBe("__class__");
-      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
-      expect(tokens[1][3].value).toBe(" ");
-      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python"]);
-      expect(tokens[1][4].value).toBe("(");
-      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
-      expect(tokens[1][5].value).toBe("foo");
-      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
-      expect(tokens[1][6].value).toBe("=");
-      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
-      expect(tokens[1][7].value).toBe("bar");
-      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
-      expect(tokens[1][8].value).toBe(")");
-      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][1].value).toBe(".");
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("__class__");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
+      expect(tokens[1][4].value).toBe(" ");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[1][5].value).toBe("(");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][6].value).toBe("foo");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[1][7].value).toBe("=");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][8].value).toBe("bar");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][9].value).toBe(")");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[2][0].value).toBe("foo");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
-      expect(tokens[2][1].value).toBe(". ");
-      expect(tokens[2][1].scopes).toEqual(["source.python"]);
-      expect(tokens[2][2].value).toBe("__add__");
-      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
-      expect(tokens[2][3].value).toBe(" ");
-      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python"]);
-      expect(tokens[2][4].value).toBe("(");
-      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
-      expect(tokens[2][5].value).toBe("foo");
-      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
-      expect(tokens[2][6].value).toBe("=");
-      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
-      expect(tokens[2][7].value).toBe("bar");
-      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
-      expect(tokens[2][8].value).toBe(")");
-      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][1].value).toBe(".");
+      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe("__add__");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[2][4].value).toBe(" ");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[2][5].value).toBe("(");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][6].value).toBe("foo");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[2][7].value).toBe("=");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][8].value).toBe("bar");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[2][9].value).toBe(")");
+      expect(tokens[2][9].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[3][0].value).toBe("foo");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
-      expect(tokens[3][1].value).toBe(". ");
-      expect(tokens[3][1].scopes).toEqual(["source.python"]);
-      expect(tokens[3][2].value).toBe("__add__");
-      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
-      expect(tokens[3][3].value).toBe("(");
-      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
-      expect(tokens[3][4].value).toBe("foo");
-      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
-      expect(tokens[3][5].value).toBe("=");
-      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
-      expect(tokens[3][6].value).toBe("bar");
-      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
-      expect(tokens[3][7].value).toBe(")");
-      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][1].value).toBe(".");
+      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("__add__");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[3][4].value).toBe("(");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][5].value).toBe("foo");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][6].value).toBe("=");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][7].value).toBe("bar");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][8].value).toBe(")");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
     });
 
   it("test/calls/call9.py", 
@@ -1010,7 +1024,7 @@ describe("Grammar Tests", function() {
       expect(tokens[6][3].value).toBe("sys");
       expect(tokens[6][3].scopes).toEqual(["source.python"]);
       expect(tokens[6][4].value).toBe(".");
-      expect(tokens[6][4].scopes).toEqual(["source.python"]);
+      expect(tokens[6][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[6][5].value).toBe("stderr");
       expect(tokens[6][5].scopes).toEqual(["source.python"]);
       expect(tokens[6][6].value).toBe(",");
@@ -1044,7 +1058,7 @@ describe("Grammar Tests", function() {
       expect(tokens[7][9].value).toBe("sys");
       expect(tokens[7][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[7][10].value).toBe(".");
-      expect(tokens[7][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[7][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.period.python"]);
       expect(tokens[7][11].value).toBe("stderr");
       expect(tokens[7][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[7][12].value).toBe(")");
@@ -1215,7 +1229,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][1].value).toBe("self");
       expect(tokens[2][1].scopes).toEqual(["source.python","variable.language.special.self.python"]);
       expect(tokens[2][2].value).toBe(".");
-      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][3].value).toBe("a");
       expect(tokens[2][3].scopes).toEqual(["source.python"]);
       expect(tokens[2][4].value).toBe(" ");
@@ -1231,7 +1245,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][1].value).toBe("self");
       expect(tokens[3][1].scopes).toEqual(["source.python","variable.language.special.self.python"]);
       expect(tokens[3][2].value).toBe(".");
-      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[3][3].value).toBe("b");
       expect(tokens[3][3].scopes).toEqual(["source.python"]);
       expect(tokens[3][4].value).toBe(" ");
@@ -1265,7 +1279,7 @@ describe("Grammar Tests", function() {
       expect(tokens[6][1].value).toBe("a");
       expect(tokens[6][1].scopes).toEqual(["source.python"]);
       expect(tokens[6][2].value).toBe(".");
-      expect(tokens[6][2].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[6][3].value).toBe("self");
       expect(tokens[6][3].scopes).toEqual(["source.python"]);
       expect(tokens[6][4].value).toBe(" ");
@@ -1281,11 +1295,11 @@ describe("Grammar Tests", function() {
       expect(tokens[7][1].value).toBe("a");
       expect(tokens[7][1].scopes).toEqual(["source.python"]);
       expect(tokens[7][2].value).toBe(".");
-      expect(tokens[7][2].scopes).toEqual(["source.python"]);
+      expect(tokens[7][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[7][3].value).toBe("self");
       expect(tokens[7][3].scopes).toEqual(["source.python"]);
       expect(tokens[7][4].value).toBe(".");
-      expect(tokens[7][4].scopes).toEqual(["source.python"]);
+      expect(tokens[7][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[7][5].value).toBe("bar");
       expect(tokens[7][5].scopes).toEqual(["source.python"]);
       expect(tokens[7][6].value).toBe(" ");
@@ -1362,7 +1376,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][1].value).toBe("cls");
       expect(tokens[3][1].scopes).toEqual(["source.python","variable.language.special.cls.python"]);
       expect(tokens[3][2].value).toBe(".");
-      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[3][3].value).toBe("a");
       expect(tokens[3][3].scopes).toEqual(["source.python"]);
       expect(tokens[3][4].value).toBe(" ");
@@ -1378,7 +1392,7 @@ describe("Grammar Tests", function() {
       expect(tokens[4][1].value).toBe("cls");
       expect(tokens[4][1].scopes).toEqual(["source.python","variable.language.special.cls.python"]);
       expect(tokens[4][2].value).toBe(".");
-      expect(tokens[4][2].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[4][3].value).toBe("b");
       expect(tokens[4][3].scopes).toEqual(["source.python"]);
       expect(tokens[4][4].value).toBe(" ");
@@ -1424,7 +1438,7 @@ describe("Grammar Tests", function() {
       expect(tokens[8][1].value).toBe("a");
       expect(tokens[8][1].scopes).toEqual(["source.python"]);
       expect(tokens[8][2].value).toBe(".");
-      expect(tokens[8][2].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[8][3].value).toBe("cls");
       expect(tokens[8][3].scopes).toEqual(["source.python"]);
       expect(tokens[8][4].value).toBe(" ");
@@ -1440,11 +1454,11 @@ describe("Grammar Tests", function() {
       expect(tokens[9][1].value).toBe("a");
       expect(tokens[9][1].scopes).toEqual(["source.python"]);
       expect(tokens[9][2].value).toBe(".");
-      expect(tokens[9][2].scopes).toEqual(["source.python"]);
+      expect(tokens[9][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[9][3].value).toBe("cls");
       expect(tokens[9][3].scopes).toEqual(["source.python"]);
       expect(tokens[9][4].value).toBe(".");
-      expect(tokens[9][4].scopes).toEqual(["source.python"]);
+      expect(tokens[9][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[9][5].value).toBe("__name__");
       expect(tokens[9][5].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[10][0].value).toBe("        ");
@@ -1506,7 +1520,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].value).toBe("f");
       expect(tokens[0][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[0][5].value).toBe(".");
-      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.period.python"]);
       expect(tokens[0][6].value).toBe("Exception");
       expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[0][7].value).toBe(",");
@@ -1516,7 +1530,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][9].value).toBe("f");
       expect(tokens[0][9].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[0][10].value).toBe(".");
-      expect(tokens[0][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.period.python"]);
       expect(tokens[0][11].value).toBe("type");
       expect(tokens[0][11].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[0][12].value).toBe(",");
@@ -1532,7 +1546,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][17].value).toBe("Exception");
       expect(tokens[0][17].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","support.type.exception.python"]);
       expect(tokens[0][18].value).toBe(".");
-      expect(tokens[0][18].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.period.python"]);
       expect(tokens[0][19].value).toBe("a");
       expect(tokens[0][19].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[0][20].value).toBe(",");
@@ -1659,7 +1673,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][4].value).toBe("Foo");
       expect(tokens[2][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[2][5].value).toBe(".");
-      expect(tokens[2][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.period.python"]);
       expect(tokens[2][6].value).toBe("Bar");
       expect(tokens[2][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[2][7].value).toBe(",");
@@ -1669,7 +1683,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][9].value).toBe("Bar");
       expect(tokens[2][9].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[2][10].value).toBe(".");
-      expect(tokens[2][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python"]);
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.period.python"]);
       expect(tokens[2][11].value).toBe("name");
       expect(tokens[2][11].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[2][12].value).toBe("=");
@@ -1947,7 +1961,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][3].value).toBe(")");
       expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[2][4].value).toBe(".");
-      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][5].value).toBe("__init__");
       expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[2][6].value).toBe("(");
@@ -1968,20 +1982,22 @@ describe("Grammar Tests", function() {
       expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[3][3].value).toBe(")");
       expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
-      expect(tokens[3][4].value).toBe(". ");
-      expect(tokens[3][4].scopes).toEqual(["source.python"]);
-      expect(tokens[3][5].value).toBe("__init__");
-      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
-      expect(tokens[3][6].value).toBe("(");
-      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
-      expect(tokens[3][7].value).toBe("foo");
-      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
-      expect(tokens[3][8].value).toBe("=");
-      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
-      expect(tokens[3][9].value).toBe("1");
-      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
-      expect(tokens[3][10].value).toBe(")");
-      expect(tokens[3][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][4].value).toBe(".");
+      expect(tokens[3][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][5].value).toBe(" ");
+      expect(tokens[3][5].scopes).toEqual(["source.python"]);
+      expect(tokens[3][6].value).toBe("__init__");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[3][7].value).toBe("(");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][8].value).toBe("foo");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][9].value).toBe("=");
+      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][10].value).toBe("1");
+      expect(tokens[3][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[3][11].value).toBe(")");
+      expect(tokens[3][11].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[4][0].value).toBe("        ");
       expect(tokens[4][0].scopes).toEqual(["source.python"]);
       expect(tokens[4][1].value).toBe("super");
@@ -1990,12 +2006,14 @@ describe("Grammar Tests", function() {
       expect(tokens[4][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[4][3].value).toBe(")");
       expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
-      expect(tokens[4][4].value).toBe(". ");
-      expect(tokens[4][4].scopes).toEqual(["source.python"]);
-      expect(tokens[4][5].value).toBe("\\");
-      expect(tokens[4][5].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
-      expect(tokens[4][6].value).toBe("");
-      expect(tokens[4][6].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe(".");
+      expect(tokens[4][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[4][5].value).toBe(" ");
+      expect(tokens[4][5].scopes).toEqual(["source.python"]);
+      expect(tokens[4][6].value).toBe("\\");
+      expect(tokens[4][6].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[4][7].value).toBe("");
+      expect(tokens[4][7].scopes).toEqual(["source.python"]);
       expect(tokens[5][0].value).toBe("__init__");
       expect(tokens[5][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[5][1].value).toBe("(");
@@ -2029,7 +2047,7 @@ describe("Grammar Tests", function() {
       expect(tokens[8][1].value).toBe("foo");
       expect(tokens[8][1].scopes).toEqual(["source.python"]);
       expect(tokens[8][2].value).toBe(".");
-      expect(tokens[8][2].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[8][3].value).toBe("__init__");
       expect(tokens[8][3].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[8][4].value).toBe("(");
@@ -4895,7 +4913,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][8].value).toBe("QQQ");
       expect(tokens[0][8].scopes).toEqual(["source.python","constant.other.caps.python"]);
       expect(tokens[0][9].value).toBe(".");
-      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][10].value).toBe("bar");
       expect(tokens[0][10].scopes).toEqual(["source.python"]);
       expect(tokens[0][11].value).toBe(" ");
@@ -4903,7 +4921,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][12].value).toBe("baz");
       expect(tokens[0][12].scopes).toEqual(["source.python"]);
       expect(tokens[0][13].value).toBe(".");
-      expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][14].value).toBe("AA_a");
       expect(tokens[0][14].scopes).toEqual(["source.python","constant.other.caps.python"]);
       expect(tokens[0][15].value).toBe(" ");
@@ -4915,7 +4933,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][18].value).toBe("foo");
       expect(tokens[0][18].scopes).toEqual(["source.python"]);
       expect(tokens[0][19].value).toBe(".");
-      expect(tokens[0][19].scopes).toEqual(["source.python"]);
+      expect(tokens[0][19].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][20].value).toBe("_AAA");
       expect(tokens[0][20].scopes).toEqual(["source.python","constant.other.caps.python"]);
       expect(tokens[1][0].value).toBe("QQQq");
@@ -4929,7 +4947,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][4].value).toBe("self");
       expect(tokens[1][4].scopes).toEqual(["source.python","variable.language.special.self.python"]);
       expect(tokens[1][5].value).toBe(".");
-      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][5].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[1][6].value).toBe("FOOO");
       expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[1][7].value).toBe("(");
@@ -5199,7 +5217,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][0].value).toBe("...");
       expect(tokens[3][0].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("__class__");
       expect(tokens[3][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
     });
@@ -5218,7 +5236,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].value).toBe("self");
       expect(tokens[0][4].scopes).toEqual(["source.python","variable.language.special.self.python"]);
       expect(tokens[0][5].value).toBe(".");
-      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][6].value).toBe("some_list");
       expect(tokens[0][6].scopes).toEqual(["source.python","meta.item-access.python"]);
       expect(tokens[0][7].value).toBe("[");
@@ -5294,7 +5312,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("foofrom");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("something");
       expect(tokens[0][2].scopes).toEqual(["source.python"]);
     });
@@ -5365,13 +5383,13 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("a");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("Exception");
       expect(tokens[0][2].scopes).toEqual(["source.python"]);
       expect(tokens[1][0].value).toBe("Exception");
       expect(tokens[1][0].scopes).toEqual(["source.python","support.type.exception.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("a");
       expect(tokens[1][2].scopes).toEqual(["source.python"]);
     });
@@ -5381,46 +5399,56 @@ describe("Grammar Tests", function() {
       tokens = grammar.tokenizeLines("a. #foo\na.\n#foo\na. \\\n#foo\na. 'bar'\na.\n'bar'\na. \\\n'bar'")
       expect(tokens[0][0].value).toBe("a");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
-      expect(tokens[0][1].value).toBe(". ");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
-      expect(tokens[0][2].value).toBe("#");
-      expect(tokens[0][2].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
-      expect(tokens[0][3].value).toBe("foo");
-      expect(tokens[0][3].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[0][1].value).toBe(".");
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][2].value).toBe(" ");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe("#");
+      expect(tokens[0][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][4].value).toBe("foo");
+      expect(tokens[0][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
       expect(tokens[1][0].value).toBe("a");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][2].value).toBe("");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
       expect(tokens[2][0].value).toBe("#");
       expect(tokens[2][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[2][1].value).toBe("foo");
       expect(tokens[2][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
       expect(tokens[3][0].value).toBe("a");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
-      expect(tokens[3][1].value).toBe(". ");
-      expect(tokens[3][1].scopes).toEqual(["source.python"]);
-      expect(tokens[3][2].value).toBe("\\");
-      expect(tokens[3][2].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
-      expect(tokens[3][3].value).toBe("");
-      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(".");
+      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("\\");
+      expect(tokens[3][3].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[3][4].value).toBe("");
+      expect(tokens[3][4].scopes).toEqual(["source.python"]);
       expect(tokens[4][0].value).toBe("#");
       expect(tokens[4][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[4][1].value).toBe("foo");
       expect(tokens[4][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
       expect(tokens[5][0].value).toBe("a");
       expect(tokens[5][0].scopes).toEqual(["source.python"]);
-      expect(tokens[5][1].value).toBe(". ");
-      expect(tokens[5][1].scopes).toEqual(["source.python"]);
-      expect(tokens[5][2].value).toBe("'");
-      expect(tokens[5][2].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[5][3].value).toBe("bar");
-      expect(tokens[5][3].scopes).toEqual(["source.python","string.quoted.single.python"]);
-      expect(tokens[5][4].value).toBe("'");
-      expect(tokens[5][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[5][1].value).toBe(".");
+      expect(tokens[5][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[5][2].value).toBe(" ");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][3].value).toBe("'");
+      expect(tokens[5][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][4].value).toBe("bar");
+      expect(tokens[5][4].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[5][5].value).toBe("'");
+      expect(tokens[5][5].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[6][0].value).toBe("a");
       expect(tokens[6][0].scopes).toEqual(["source.python"]);
       expect(tokens[6][1].value).toBe(".");
-      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[6][2].value).toBe("");
+      expect(tokens[6][2].scopes).toEqual(["source.python"]);
       expect(tokens[7][0].value).toBe("'");
       expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[7][1].value).toBe("bar");
@@ -5429,12 +5457,14 @@ describe("Grammar Tests", function() {
       expect(tokens[7][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[8][0].value).toBe("a");
       expect(tokens[8][0].scopes).toEqual(["source.python"]);
-      expect(tokens[8][1].value).toBe(". ");
-      expect(tokens[8][1].scopes).toEqual(["source.python"]);
-      expect(tokens[8][2].value).toBe("\\");
-      expect(tokens[8][2].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
-      expect(tokens[8][3].value).toBe("");
-      expect(tokens[8][3].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe(".");
+      expect(tokens[8][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[8][2].value).toBe(" ");
+      expect(tokens[8][2].scopes).toEqual(["source.python"]);
+      expect(tokens[8][3].value).toBe("\\");
+      expect(tokens[8][3].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[8][4].value).toBe("");
+      expect(tokens[8][4].scopes).toEqual(["source.python"]);
       expect(tokens[9][0].value).toBe("'");
       expect(tokens[9][0].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[9][1].value).toBe("bar");
@@ -5813,7 +5843,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("a");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("True");
       expect(tokens[0][2].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
       expect(tokens[0][3].value).toBe(" ");
@@ -5825,7 +5855,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][6].value).toBe("b");
       expect(tokens[0][6].scopes).toEqual(["source.python"]);
       expect(tokens[0][7].value).toBe(".");
-      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][8].value).toBe("False");
       expect(tokens[0][8].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
       expect(tokens[0][9].value).toBe(" ");
@@ -5837,7 +5867,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][12].value).toBe("d");
       expect(tokens[0][12].scopes).toEqual(["source.python"]);
       expect(tokens[0][13].value).toBe(".");
-      expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][14].value).toBe("None");
       expect(tokens[0][14].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
     });
@@ -6143,7 +6173,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("self");
       expect(tokens[0][0].scopes).toEqual(["source.python","variable.language.special.self.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("assertEqual");
       expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[0][3].value).toBe("(");
@@ -7248,7 +7278,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][19].value).toBe("fo");
       expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python"]);
       expect(tokens[0][20].value).toBe(".");
-      expect(tokens[0][20].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.fstring.python","punctuation.separator.period.python"]);
       expect(tokens[0][21].value).toBe("__add__");
       expect(tokens[0][21].scopes).toEqual(["source.python","meta.fstring.python","support.function.magic.python"]);
       expect(tokens[0][22].value).toBe("!s");
@@ -9825,7 +9855,7 @@ describe("Grammar Tests", function() {
       expect(tokens[4][7].value).toBe(")");
       expect(tokens[4][7].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
       expect(tokens[4][8].value).toBe(".");
-      expect(tokens[4][8].scopes).toEqual(["source.python"]);
+      expect(tokens[4][8].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[4][9].value).toBe("fuuuu");
       expect(tokens[4][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[4][10].value).toBe("(");
@@ -11409,7 +11439,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][4].value).toBe("re");
       expect(tokens[2][4].scopes).toEqual(["source.python"]);
       expect(tokens[2][5].value).toBe(".");
-      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][5].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][6].value).toBe("compile");
       expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[2][7].value).toBe("(");
@@ -11723,7 +11753,7 @@ describe("Grammar Tests", function() {
       expect(tokens[20][4].value).toBe("re");
       expect(tokens[20][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[20][5].value).toBe(".");
-      expect(tokens[20][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[20][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.period.python"]);
       expect(tokens[20][6].value).toBe("ASCII");
       expect(tokens[20][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.other.caps.python"]);
       expect(tokens[20][7].value).toBe(")");
@@ -11997,32 +12027,34 @@ describe("Grammar Tests", function() {
       tokens = grammar.tokenizeLines("from ...foo import bar as spam, baz\nimport time as ham, datetime")
       expect(tokens[0][0].value).toBe("from");
       expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
-      expect(tokens[0][1].value).toBe(" ...");
+      expect(tokens[0][1].value).toBe(" ");
       expect(tokens[0][1].scopes).toEqual(["source.python"]);
-      expect(tokens[0][2].value).toBe("foo");
-      expect(tokens[0][2].scopes).toEqual(["source.python"]);
-      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][2].value).toBe("...");
+      expect(tokens[0][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][3].value).toBe("foo");
       expect(tokens[0][3].scopes).toEqual(["source.python"]);
-      expect(tokens[0][4].value).toBe("import");
-      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
-      expect(tokens[0][5].value).toBe(" ");
-      expect(tokens[0][5].scopes).toEqual(["source.python"]);
-      expect(tokens[0][6].value).toBe("bar");
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("import");
+      expect(tokens[0][5].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][6].value).toBe(" ");
       expect(tokens[0][6].scopes).toEqual(["source.python"]);
-      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].value).toBe("bar");
       expect(tokens[0][7].scopes).toEqual(["source.python"]);
-      expect(tokens[0][8].value).toBe("as");
-      expect(tokens[0][8].scopes).toEqual(["source.python","keyword.control.flow.python"]);
-      expect(tokens[0][9].value).toBe(" ");
-      expect(tokens[0][9].scopes).toEqual(["source.python"]);
-      expect(tokens[0][10].value).toBe("spam");
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe("as");
+      expect(tokens[0][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][10].value).toBe(" ");
       expect(tokens[0][10].scopes).toEqual(["source.python"]);
-      expect(tokens[0][11].value).toBe(",");
-      expect(tokens[0][11].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
-      expect(tokens[0][12].value).toBe(" ");
-      expect(tokens[0][12].scopes).toEqual(["source.python"]);
-      expect(tokens[0][13].value).toBe("baz");
+      expect(tokens[0][11].value).toBe("spam");
+      expect(tokens[0][11].scopes).toEqual(["source.python"]);
+      expect(tokens[0][12].value).toBe(",");
+      expect(tokens[0][12].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][13].value).toBe(" ");
       expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[0][14].value).toBe("baz");
+      expect(tokens[0][14].scopes).toEqual(["source.python"]);
       expect(tokens[1][0].value).toBe("import");
       expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[1][1].value).toBe(" ");
@@ -12050,34 +12082,46 @@ describe("Grammar Tests", function() {
       tokens = grammar.tokenizeLines("from .... import a\nfrom ... import b\nfrom .. import c")
       expect(tokens[0][0].value).toBe("from");
       expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
-      expect(tokens[0][1].value).toBe(" .... ");
+      expect(tokens[0][1].value).toBe(" ");
       expect(tokens[0][1].scopes).toEqual(["source.python"]);
-      expect(tokens[0][2].value).toBe("import");
-      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][2].value).toBe("....");
+      expect(tokens[0][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][3].value).toBe(" ");
       expect(tokens[0][3].scopes).toEqual(["source.python"]);
-      expect(tokens[0][4].value).toBe("a");
-      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("import");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("a");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
       expect(tokens[1][0].value).toBe("from");
       expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
-      expect(tokens[1][1].value).toBe(" ... ");
+      expect(tokens[1][1].value).toBe(" ");
       expect(tokens[1][1].scopes).toEqual(["source.python"]);
-      expect(tokens[1][2].value).toBe("import");
-      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][2].value).toBe("...");
+      expect(tokens[1][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[1][3].value).toBe(" ");
       expect(tokens[1][3].scopes).toEqual(["source.python"]);
-      expect(tokens[1][4].value).toBe("b");
-      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("import");
+      expect(tokens[1][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("b");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
       expect(tokens[2][0].value).toBe("from");
       expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
-      expect(tokens[2][1].value).toBe(" .. ");
+      expect(tokens[2][1].value).toBe(" ");
       expect(tokens[2][1].scopes).toEqual(["source.python"]);
-      expect(tokens[2][2].value).toBe("import");
-      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[2][2].value).toBe("..");
+      expect(tokens[2][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][3].value).toBe(" ");
       expect(tokens[2][3].scopes).toEqual(["source.python"]);
-      expect(tokens[2][4].value).toBe("c");
-      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("import");
+      expect(tokens[2][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("c");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
     });
 
   it("test/statements/import3.py", 
@@ -12086,7 +12130,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("from");
       expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[0][1].value).toBe("....");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("import");
       expect(tokens[0][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[0][3].value).toBe(" ");
@@ -12096,7 +12140,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].value).toBe("from");
       expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[1][1].value).toBe("...");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("import");
       expect(tokens[1][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[1][3].value).toBe(" ");
@@ -12106,7 +12150,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][0].value).toBe("from");
       expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[2][1].value).toBe("..");
-      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("import");
       expect(tokens[2][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[2][3].value).toBe(" ");
@@ -12116,7 +12160,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][0].value).toBe("from");
       expect(tokens[3][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("import");
       expect(tokens[3][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[3][3].value).toBe(" ");
@@ -12131,7 +12175,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("from");
       expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[0][1].value).toBe("....");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("foo");
       expect(tokens[0][2].scopes).toEqual(["source.python"]);
       expect(tokens[0][3].value).toBe(" ");
@@ -12145,7 +12189,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].value).toBe("from");
       expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[1][1].value).toBe("...");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("foo");
       expect(tokens[1][2].scopes).toEqual(["source.python"]);
       expect(tokens[1][3].value).toBe(" ");
@@ -12159,7 +12203,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][0].value).toBe("from");
       expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[2][1].value).toBe("..");
-      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("foo");
       expect(tokens[2][2].scopes).toEqual(["source.python"]);
       expect(tokens[2][3].value).toBe(" ");
@@ -12173,7 +12217,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][0].value).toBe("from");
       expect(tokens[3][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("foo");
       expect(tokens[3][2].scopes).toEqual(["source.python"]);
       expect(tokens[3][3].value).toBe(" ");
@@ -12192,7 +12236,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("from");
       expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("foo");
       expect(tokens[0][2].scopes).toEqual(["source.python"]);
       expect(tokens[0][3].value).toBe(" ");
@@ -12206,7 +12250,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].value).toBe("from");
       expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("import");
       expect(tokens[1][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[1][3].value).toBe(" ");
@@ -12218,7 +12262,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][0].value).toBe("foo");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("import");
       expect(tokens[3][2].scopes).toEqual(["source.python","keyword.control.flow.python"]);
       expect(tokens[4][0].value).toBe("");
@@ -13158,7 +13202,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][17].value).toBe("\"");
       expect(tokens[0][17].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[0][18].value).toBe(".");
-      expect(tokens[0][18].scopes).toEqual(["source.python"]);
+      expect(tokens[0][18].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[0][19].value).toBe("format");
       expect(tokens[0][19].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[0][20].value).toBe("(");
diff --git a/test/builtins/builtins3.py b/test/builtins/builtins3.py
index fd3db478..02ccb5af 100644
--- a/test/builtins/builtins3.py
+++ b/test/builtins/builtins3.py
@@ -60,127 +60,127 @@
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 ]             : punctuation.definition.list.end.python, source.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __bases__     : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __class__     : source.python, support.variable.magic.python
 assert        : keyword.control.flow.python, source.python
               : source.python
 __debug__     : source.python, support.variable.magic.python
 __builtins__  : source.python, support.variable.magic.python
 __builtins__  : source.python, support.variable.magic.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 len           : source.python
 print         : meta.function-call.python, source.python, support.function.builtin.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 __builtins__  : meta.function-call.arguments.python, meta.function-call.python, source.python, support.variable.magic.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __dict__      : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __doc__       : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __file__      : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __members__   : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __metaclass__ : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __methods__   : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __module__    : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __mro__       : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __name__      : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __slots__     : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __subclasses__ : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __version__   : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __weakref__   : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __qualname__  : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __code__      : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __wrapped__   : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __signature__ : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __defaults__  : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __func__      : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __self__      : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __kwdefaults__ : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __matmul__    : source.python, support.function.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __imatmul__   : source.python, support.function.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __rmatmul__   : source.python, support.function.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __annotations__ : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __init_subclass__ : source.python, support.function.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __set_name__  : source.python, support.function.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __fspath__    : source.python, support.function.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __classcell__ : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __bytes__     : source.python, support.function.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __spec__      : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __path__      : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __prepare__   : source.python, support.function.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __package__   : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __traceback__ : source.python, support.variable.magic.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __notspecial__ : source.python
diff --git a/test/builtins/builtins4.py b/test/builtins/builtins4.py
index b78b96fb..b8f3401b 100644
--- a/test/builtins/builtins4.py
+++ b/test/builtins/builtins4.py
@@ -8,20 +8,20 @@
 
 
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 int           : source.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 sum           : source.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 super         : source.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 unicode       : source.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 foo           : source.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 Exception     : source.python
diff --git a/test/builtins/builtins5.py b/test/builtins/builtins5.py
index ecabf1c5..674df37f 100644
--- a/test/builtins/builtins5.py
+++ b/test/builtins/builtins5.py
@@ -8,16 +8,19 @@
 
 
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 True          : keyword.illegal.name.python, source.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 \             : punctuation.separator.continuation.line.python, source.python
               : source.python
               : source.python
 True          : keyword.illegal.name.python, source.python
 True          : constant.language.python, source.python
 some          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
               : source.python
 True          : keyword.illegal.name.python, source.python
diff --git a/test/calls/call3.py b/test/calls/call3.py
index 3818b51c..3e5bca3d 100644
--- a/test/calls/call3.py
+++ b/test/calls/call3.py
@@ -5,16 +5,16 @@
 
 
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 class         : keyword.control.flow.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 a             : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 and           : keyword.control.flow.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 if            : keyword.control.flow.python, source.python
diff --git a/test/calls/call4.py b/test/calls/call4.py
index 50f561c0..a2976601 100644
--- a/test/calls/call4.py
+++ b/test/calls/call4.py
@@ -5,7 +5,7 @@
 
 
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 1             : source.python
 foo           : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
@@ -19,13 +19,13 @@
 sam           : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 None          : keyword.illegal.name.python, source.python
               : source.python
 and           : keyword.operator.logical.python, source.python
               : source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 None          : keyword.illegal.name.python, source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 baz           : source.python
diff --git a/test/calls/call7.py b/test/calls/call7.py
index 87242cc7..b0b00f05 100644
--- a/test/calls/call7.py
+++ b/test/calls/call7.py
@@ -8,7 +8,7 @@
 
 
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __class__     : meta.function-call.python, source.python, support.variable.magic.python
               : meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
@@ -17,7 +17,7 @@
 bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __class__     : meta.function-call.python, source.python, support.variable.magic.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
@@ -25,7 +25,7 @@
 bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __add__       : meta.function-call.python, source.python, support.function.magic.python
               : meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
@@ -34,7 +34,7 @@
 bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __add__       : meta.function-call.python, source.python, support.function.magic.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
@@ -43,7 +43,7 @@
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
               : source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __class__     : source.python, support.variable.magic.python
               : source.python
 1             : constant.numeric.dec.python, source.python
diff --git a/test/calls/call8.py b/test/calls/call8.py
index 062a527f..471a64d3 100644
--- a/test/calls/call8.py
+++ b/test/calls/call8.py
@@ -6,7 +6,8 @@
 
 
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 __class__     : meta.function-call.python, source.python, support.variable.magic.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
@@ -14,7 +15,8 @@
 bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 __class__     : meta.function-call.python, source.python, support.variable.magic.python
               : meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
@@ -23,7 +25,8 @@
 bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 __add__       : meta.function-call.python, source.python, support.function.magic.python
               : meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
@@ -32,7 +35,8 @@
 bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 __add__       : meta.function-call.python, source.python, support.function.magic.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
diff --git a/test/calls/print1.py b/test/calls/print1.py
index 6b1848c5..c5f3e7f7 100644
--- a/test/calls/print1.py
+++ b/test/calls/print1.py
@@ -55,7 +55,7 @@
               : source.python
 >>            : keyword.operator.bitwise.python, source.python
 sys           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 stderr        : source.python
 ,             : punctuation.separator.element.python, source.python
               : source.python
@@ -72,7 +72,7 @@
 file          : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
 =             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 sys           : meta.function-call.arguments.python, meta.function-call.python, source.python
-.             : meta.function-call.arguments.python, meta.function-call.python, source.python
+.             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.period.python, source.python
 stderr        : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 print         : meta.function-call.python, source.python, support.function.builtin.python
diff --git a/test/classes/class11.py b/test/classes/class11.py
index 6083dc95..bad00706 100644
--- a/test/classes/class11.py
+++ b/test/classes/class11.py
@@ -32,7 +32,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 :             : meta.function.python, punctuation.section.function.begin.python, source.python
               : source.python
 self          : source.python, variable.language.special.self.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 a             : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
@@ -40,7 +40,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 a             : source.python
               : source.python
 self          : source.python, variable.language.special.self.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 b             : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
@@ -57,7 +57,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
               : source.python
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 self          : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
@@ -65,9 +65,9 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 1             : constant.numeric.dec.python, source.python
               : source.python
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 self          : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 bar           : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
diff --git a/test/classes/class12.py b/test/classes/class12.py
index 90e656bf..e8b69161 100644
--- a/test/classes/class12.py
+++ b/test/classes/class12.py
@@ -37,7 +37,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 :             : meta.function.python, punctuation.section.function.begin.python, source.python
               : source.python
 cls           : source.python, variable.language.special.cls.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 a             : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
@@ -45,7 +45,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 a             : source.python
               : source.python
 cls           : source.python, variable.language.special.cls.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 b             : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
@@ -68,7 +68,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 1             : constant.numeric.dec.python, source.python
               : source.python
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 cls           : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
@@ -76,9 +76,9 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 1             : constant.numeric.dec.python, source.python
               : source.python
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 cls           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __name__      : source.python, support.variable.magic.python
               : source.python
 cls           : meta.item-access.python, source.python, variable.language.special.cls.python
diff --git a/test/classes/class14.py b/test/classes/class14.py
index 036543ed..706969f9 100644
--- a/test/classes/class14.py
+++ b/test/classes/class14.py
@@ -8,12 +8,12 @@ class         : meta.class.python, source.python, storage.type.class.python
 F             : entity.name.type.class.python, meta.class.python, source.python
 (             : meta.class.inheritance.python, meta.class.python, punctuation.definition.inheritance.begin.python, source.python
 f             : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
-.             : meta.class.inheritance.python, meta.class.python, source.python
+.             : meta.class.inheritance.python, meta.class.python, punctuation.separator.period.python, source.python
 Exception     : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
 ,             : meta.class.inheritance.python, meta.class.python, punctuation.separator.inheritance.python, source.python
               : meta.class.inheritance.python, meta.class.python, source.python
 f             : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
-.             : meta.class.inheritance.python, meta.class.python, source.python
+.             : meta.class.inheritance.python, meta.class.python, punctuation.separator.period.python, source.python
 type          : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
 ,             : meta.class.inheritance.python, meta.class.python, punctuation.separator.inheritance.python, source.python
               : meta.class.inheritance.python, meta.class.python, source.python
@@ -21,7 +21,7 @@ class         : meta.class.python, source.python, storage.type.class.python
 ,             : meta.class.inheritance.python, meta.class.python, punctuation.separator.inheritance.python, source.python
               : meta.class.inheritance.python, meta.class.python, source.python
 Exception     : meta.class.inheritance.python, meta.class.python, source.python, support.type.exception.python
-.             : meta.class.inheritance.python, meta.class.python, source.python
+.             : meta.class.inheritance.python, meta.class.python, punctuation.separator.period.python, source.python
 a             : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
 ,             : meta.class.inheritance.python, meta.class.python, punctuation.separator.inheritance.python, source.python
               : meta.class.inheritance.python, meta.class.python, source.python
diff --git a/test/classes/class2.py b/test/classes/class2.py
index bba5e52d..536f9258 100644
--- a/test/classes/class2.py
+++ b/test/classes/class2.py
@@ -14,12 +14,12 @@ class         : meta.class.python, source.python, storage.type.class.python
 Spam          : entity.name.type.class.python, meta.class.python, source.python
 (             : meta.class.inheritance.python, meta.class.python, punctuation.definition.inheritance.begin.python, source.python
 Foo           : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
-.             : meta.class.inheritance.python, meta.class.python, source.python
+.             : meta.class.inheritance.python, meta.class.python, punctuation.separator.period.python, source.python
 Bar           : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
 ,             : meta.class.inheritance.python, meta.class.python, punctuation.separator.inheritance.python, source.python
               : meta.class.inheritance.python, meta.class.python, source.python
 Bar           : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
-.             : meta.class.inheritance.python, meta.class.python, source.python
+.             : meta.class.inheritance.python, meta.class.python, punctuation.separator.period.python, source.python
 name          : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
 =             : keyword.operator.assignment.python, meta.class.inheritance.python, meta.class.python, source.python
 {             : meta.class.inheritance.python, meta.class.python, punctuation.definition.dict.begin.python, source.python
diff --git a/test/classes/super1.py b/test/classes/super1.py
index 5172f365..1840ed9b 100644
--- a/test/classes/super1.py
+++ b/test/classes/super1.py
@@ -30,7 +30,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 super         : meta.function-call.python, source.python, support.type.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __init__      : meta.function-call.python, source.python, support.function.magic.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
@@ -41,7 +41,8 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 super         : meta.function-call.python, source.python, support.type.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 __init__      : meta.function-call.python, source.python, support.function.magic.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
@@ -52,7 +53,8 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 super         : meta.function-call.python, source.python, support.type.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 \             : punctuation.separator.continuation.line.python, source.python
               : source.python
 __init__      : meta.function-call.python, source.python, support.function.magic.python
@@ -71,7 +73,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : source.python
               : source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __init__      : meta.function-call.python, source.python, support.function.magic.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 bar           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
diff --git a/test/expressions/const1.py b/test/expressions/const1.py
index 8e19a502..e59a19be 100644
--- a/test/expressions/const1.py
+++ b/test/expressions/const1.py
@@ -12,24 +12,24 @@
 PROTOCOL_v2   : constant.other.caps.python, source.python
               : source.python
 QQQ           : constant.other.caps.python, source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 bar           : source.python
               : source.python
 baz           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 AA_a          : constant.other.caps.python, source.python
               : source.python
 _AAA          : constant.other.caps.python, source.python
               : source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 _AAA          : constant.other.caps.python, source.python
 QQQq          : source.python
               : source.python
 QQQq123       : source.python
               : source.python
 self          : source.python, variable.language.special.self.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 FOOO          : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/expressions/expr10.py b/test/expressions/expr10.py
index 0a14b7df..501fb475 100644
--- a/test/expressions/expr10.py
+++ b/test/expressions/expr10.py
@@ -32,5 +32,5 @@
 ...           : constant.other.ellipsis.python, source.python
 )             : punctuation.parenthesis.end.python, source.python
 ...           : constant.other.ellipsis.python, source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 __class__     : source.python, support.variable.magic.python
diff --git a/test/expressions/expr11.py b/test/expressions/expr11.py
index 584174eb..142ff621 100644
--- a/test/expressions/expr11.py
+++ b/test/expressions/expr11.py
@@ -7,7 +7,7 @@
 =             : keyword.operator.assignment.python, source.python
               : source.python
 self          : source.python, variable.language.special.self.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 some_list     : meta.item-access.python, source.python
 [             : meta.item-access.python, punctuation.definition.arguments.begin.python, source.python
 1             : constant.numeric.dec.python, meta.item-access.arguments.python, meta.item-access.python, source.python
diff --git a/test/expressions/expr15.py b/test/expressions/expr15.py
index 80558f9d..2815cdae 100644
--- a/test/expressions/expr15.py
+++ b/test/expressions/expr15.py
@@ -3,5 +3,5 @@
 
 
 foofrom       : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 something     : source.python
diff --git a/test/expressions/expr18.py b/test/expressions/expr18.py
index 41ed45db..8326520f 100644
--- a/test/expressions/expr18.py
+++ b/test/expressions/expr18.py
@@ -4,8 +4,8 @@
 
 
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 Exception     : source.python
 Exception     : source.python, support.type.exception.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 a             : source.python
diff --git a/test/expressions/expr19.py b/test/expressions/expr19.py
index 604b9b84..45dd0e8e 100644
--- a/test/expressions/expr19.py
+++ b/test/expressions/expr19.py
@@ -12,31 +12,37 @@
 
 
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
 foo           : comment.line.number-sign.python, source.python
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
 foo           : comment.line.number-sign.python, source.python
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 \             : punctuation.separator.continuation.line.python, source.python
               : source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
 foo           : comment.line.number-sign.python, source.python
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 bar           : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.single.python
 bar           : source.python, string.quoted.docstring.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.docstring.single.python
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
 \             : punctuation.separator.continuation.line.python, source.python
               : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
diff --git a/test/expressions/expr7.py b/test/expressions/expr7.py
index eef5c56e..936af9e8 100644
--- a/test/expressions/expr7.py
+++ b/test/expressions/expr7.py
@@ -3,17 +3,17 @@
 
 
 a             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 True          : keyword.illegal.name.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 b             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 False         : keyword.illegal.name.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 d             : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 None          : keyword.illegal.name.python, source.python
diff --git a/test/fstrings/comment4.py b/test/fstrings/comment4.py
index 793efc35..f070cdd0 100644
--- a/test/fstrings/comment4.py
+++ b/test/fstrings/comment4.py
@@ -4,7 +4,7 @@
 
 
 self          : source.python, variable.language.special.self.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 assertEqual   : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 f             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
diff --git a/test/fstrings/simple2.py b/test/fstrings/simple2.py
index 967bb1f3..48ce0dcd 100644
--- a/test/fstrings/simple2.py
+++ b/test/fstrings/simple2.py
@@ -22,7 +22,7 @@
  normal       : meta.fstring.python, source.python, string.interpolated.python, string.quoted.single.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 fo            : meta.fstring.python, source.python
-.             : meta.fstring.python, source.python
+.             : meta.fstring.python, punctuation.separator.period.python, source.python
 __add__       : meta.fstring.python, source.python, support.function.magic.python
 !s            : meta.fstring.python, source.python, storage.type.format.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
diff --git a/test/illegals/illegal1.py b/test/illegals/illegal1.py
index 61c22dce..6010bc4f 100644
--- a/test/illegals/illegal1.py
+++ b/test/illegals/illegal1.py
@@ -28,7 +28,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 .class        : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 )             : punctuation.parenthesis.end.python, source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 fuuuu         : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 baz           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
diff --git a/test/regexp/python8.py b/test/regexp/python8.py
index b0080e77..f0babc73 100644
--- a/test/regexp/python8.py
+++ b/test/regexp/python8.py
@@ -30,7 +30,7 @@
 =             : keyword.operator.assignment.python, source.python
               : source.python
 re            : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 compile       : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 r             : meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.regexp.quoted.multi.python
@@ -187,7 +187,7 @@
 ,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
               : meta.function-call.arguments.python, meta.function-call.python, source.python
 re            : meta.function-call.arguments.python, meta.function-call.python, source.python
-.             : meta.function-call.arguments.python, meta.function-call.python, source.python
+.             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.period.python, source.python
 ASCII         : constant.other.caps.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
                   : source.python
diff --git a/test/statements/import1.py b/test/statements/import1.py
index 1e322e8f..f41b72c5 100644
--- a/test/statements/import1.py
+++ b/test/statements/import1.py
@@ -4,7 +4,8 @@
 
 
 from          : keyword.control.import.python, source.python
- ...          : source.python
+              : source.python
+...           : punctuation.separator.period.python, source.python
 foo           : source.python
               : source.python
 import        : keyword.control.import.python, source.python
diff --git a/test/statements/import2.py b/test/statements/import2.py
index 18a8049e..842f68d2 100644
--- a/test/statements/import2.py
+++ b/test/statements/import2.py
@@ -5,17 +5,23 @@
 
 
 from          : keyword.control.import.python, source.python
- ....         : source.python
+              : source.python
+....          : punctuation.separator.period.python, source.python
+              : source.python
 import        : keyword.control.import.python, source.python
               : source.python
 a             : source.python
 from          : keyword.control.import.python, source.python
- ...          : source.python
+              : source.python
+...           : punctuation.separator.period.python, source.python
+              : source.python
 import        : keyword.control.import.python, source.python
               : source.python
 b             : source.python
 from          : keyword.control.import.python, source.python
- ..           : source.python
+              : source.python
+..            : punctuation.separator.period.python, source.python
+              : source.python
 import        : keyword.control.import.python, source.python
               : source.python
 c             : source.python
diff --git a/test/statements/import3.py b/test/statements/import3.py
index 79f06128..1952bf59 100644
--- a/test/statements/import3.py
+++ b/test/statements/import3.py
@@ -6,22 +6,22 @@
 
 
 from          : keyword.control.import.python, source.python
-....          : source.python
+....          : punctuation.separator.period.python, source.python
 import        : keyword.control.import.python, source.python
               : source.python
 a             : source.python
 from          : keyword.control.import.python, source.python
-...           : source.python
+...           : punctuation.separator.period.python, source.python
 import        : keyword.control.import.python, source.python
               : source.python
 b             : source.python
 from          : keyword.control.import.python, source.python
-..            : source.python
+..            : punctuation.separator.period.python, source.python
 import        : keyword.control.import.python, source.python
               : source.python
 c             : source.python
 from          : keyword.control.import.python, source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 import        : keyword.control.import.python, source.python
               : source.python
 d             : source.python
diff --git a/test/statements/import4.py b/test/statements/import4.py
index c45b328d..b2cee743 100644
--- a/test/statements/import4.py
+++ b/test/statements/import4.py
@@ -6,28 +6,28 @@
 
 
 from          : keyword.control.import.python, source.python
-....          : source.python
+....          : punctuation.separator.period.python, source.python
 foo           : source.python
               : source.python
 import        : keyword.control.import.python, source.python
               : source.python
 a             : source.python
 from          : keyword.control.import.python, source.python
-...           : source.python
+...           : punctuation.separator.period.python, source.python
 foo           : source.python
               : source.python
 import        : keyword.control.import.python, source.python
               : source.python
 b             : source.python
 from          : keyword.control.import.python, source.python
-..            : source.python
+..            : punctuation.separator.period.python, source.python
 foo           : source.python
               : source.python
 import        : keyword.control.import.python, source.python
               : source.python
 c             : source.python
 from          : keyword.control.import.python, source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 foo           : source.python
               : source.python
 import        : keyword.control.import.python, source.python
diff --git a/test/statements/import5.py b/test/statements/import5.py
index a805e4d3..2df920d6 100644
--- a/test/statements/import5.py
+++ b/test/statements/import5.py
@@ -11,20 +11,20 @@ def bar():
 
 
 from          : keyword.control.import.python, source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 foo           : source.python
               : source.python
 import        : keyword.control.import.python, source.python
               : source.python
 d             : source.python
 from          : keyword.control.import.python, source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 import        : keyword.control.import.python, source.python
               : source.python
 a             : source.python
               : source.python
 foo           : source.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 import        : keyword.control.flow.python, source.python
               : source.python
 raise         : keyword.control.flow.python, source.python
diff --git a/test/strings/format2.py b/test/strings/format2.py
index e9b0c240..41c1baed 100644
--- a/test/strings/format2.py
+++ b/test/strings/format2.py
@@ -20,7 +20,7 @@
 !s            : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
 }             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
-.             : source.python
+.             : punctuation.separator.period.python, source.python
 format        : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 fo            : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python

From 935abefebfd4a75fe5741a99de0b51a7542efb5b Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Thu, 10 Aug 2017 22:49:29 -0400
Subject: [PATCH 32/65] Prepare 1.0.12 release

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 759d184b..7673f4fd 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "MagicPython",
-  "version": "1.0.11",
+  "version": "1.0.12",
   "engines": {
     "atom": "*",
     "node": "*",

From f340032d0ed35f0b94323537f95cb256ea82ebb5 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Tue, 10 Jul 2018 14:33:43 -0400
Subject: [PATCH 33/65] Fix a docstring highlighter bug.

---
 Makefile                              |  2 +-
 grammars/MagicPython.cson             | 11 ++--
 grammars/MagicPython.tmLanguage       | 12 ++--
 grammars/src/MagicPython.syntax.yaml  | 10 ++-
 grammars/src/pystring.inc.syntax.yaml |  2 +-
 package.json                          |  4 ++
 test/atom-spec/python-spec.js         | 91 +++++++++++++++++++++++++--
 test/docstrings/continuation2.py      |  3 +
 test/docstrings/continuation5.py      | 47 ++++++++++++++
 test/fstrings/nested3.py              |  4 +-
 test/illegals/backticks3.py           |  3 +
 test/regexp/python2.py                |  3 +
 12 files changed, 172 insertions(+), 20 deletions(-)
 create mode 100644 test/docstrings/continuation5.py

diff --git a/Makefile b/Makefile
index 2d09f37c..f690dbd9 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ ci-test: release
 		then echo "Error: package.version != git.tag" && exit 1 ; fi
 
 test: ci-test
-	atom -t .
+	atom -t test/atom-spec
 
 devenv:
 	npm install syntaxdev@0.0.16
diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 526b2873..8dff74fb 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -129,7 +129,8 @@ repository:
     ]
   "docstring-statement":
     begin: "^(?=\\s*[rR]?(\\'\\'\\'|\\\"\\\"\\\"|\\'|\\\"))"
-    end: "(?<=\\'\\'\\'|\\\"\\\"\\\"|\\'|\\\")"
+    comment: "the string either terminates correctly or by the beginning of a new line (this is for single line docstrings that aren't terminated) AND it's not followed by another docstring"
+    end: "((?<=\\1)|^)(?!\\s*[rR]?(\\'\\'\\'|\\\"\\\"\\\"|\\'|\\\"))"
     patterns: [
       {
         include: "#docstring"
@@ -186,7 +187,7 @@ repository:
       {
         name: "string.quoted.docstring.single.python"
         begin: "(\\'|\\\")"
-        end: "(\\1)|((?<!\\\\)\\n)"
+        end: "(\\1)|(\\n)"
         beginCaptures:
           "1":
             name: "punctuation.definition.string.begin.python"
@@ -207,7 +208,7 @@ repository:
       {
         name: "string.quoted.docstring.raw.single.python"
         begin: "([rR])(\\'|\\\")"
-        end: "(\\2)|((?<!\\\\)\\n)"
+        end: "(\\2)|(\\n)"
         beginCaptures:
           "1":
             name: "storage.type.string.python"
@@ -4177,7 +4178,7 @@ repository:
     ]
   "string-quoted-single-line":
     name: "string.quoted.single.python"
-    begin: "(\\b[rR](?=[uU]))?([uU])?((['\"]))"
+    begin: "(?:\\b([rR])(?=[uU]))?([uU])?((['\"]))"
     end: "(\\3)|((?<!\\\\)\\n)"
     beginCaptures:
       "1":
@@ -4351,7 +4352,7 @@ repository:
     ]
   "string-quoted-multi-line":
     name: "string.quoted.multi.python"
-    begin: "(\\b[rR](?=[uU]))?([uU])?('''|\"\"\")"
+    begin: "(?:\\b([rR])(?=[uU]))?([uU])?('''|\"\"\")"
     end: "(\\3)"
     beginCaptures:
       "1":
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index ae03ed0e..de83a6bc 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -184,8 +184,10 @@
       <dict>
         <key>begin</key>
         <string>^(?=\s*[rR]?(\'\'\'|\"\"\"|\'|\"))</string>
+        <key>comment</key>
+        <string>the string either terminates correctly or by the beginning of a new line (this is for single line docstrings that aren't terminated) AND it's not followed by another docstring</string>
         <key>end</key>
-        <string>(?&lt;=\'\'\'|\"\"\"|\'|\")</string>
+        <string>((?&lt;=\1)|^)(?!\s*[rR]?(\'\'\'|\"\"\"|\'|\"))</string>
         <key>patterns</key>
         <array>
           <dict>
@@ -287,7 +289,7 @@
             <key>begin</key>
             <string>(\'|\")</string>
             <key>end</key>
-            <string>(\1)|((?&lt;!\\)\n)</string>
+            <string>(\1)|(\n)</string>
             <key>beginCaptures</key>
             <dict>
               <key>1</key>
@@ -327,7 +329,7 @@
             <key>begin</key>
             <string>([rR])(\'|\")</string>
             <key>end</key>
-            <string>(\2)|((?&lt;!\\)\n)</string>
+            <string>(\2)|(\n)</string>
             <key>beginCaptures</key>
             <dict>
               <key>1</key>
@@ -7365,7 +7367,7 @@ indirectly through syntactic constructs
         <key>name</key>
         <string>string.quoted.single.python</string>
         <key>begin</key>
-        <string>(\b[rR](?=[uU]))?([uU])?((['"]))</string>
+        <string>(?:\b([rR])(?=[uU]))?([uU])?((['"]))</string>
         <key>end</key>
         <string>(\3)|((?&lt;!\\)\n)</string>
         <key>beginCaptures</key>
@@ -7665,7 +7667,7 @@ indirectly through syntactic constructs
         <key>name</key>
         <string>string.quoted.multi.python</string>
         <key>begin</key>
-        <string>(\b[rR](?=[uU]))?([uU])?('''|""")</string>
+        <string>(?:\b([rR])(?=[uU]))?([uU])?('''|""")</string>
         <key>end</key>
         <string>(\3)</string>
         <key>beginCaptures</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 43009579..334e439e 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -279,7 +279,11 @@ repository:
 
   docstring-statement:
     begin: ^(?=\s*[rR]?(\'\'\'|\"\"\"|\'|\"))
-    end: (?<=\'\'\'|\"\"\"|\'|\")
+    comment: the string either terminates correctly or by the
+             beginning of a new line (this is for single line
+             docstrings that aren't terminated) AND it's not followed
+             by another docstring
+    end: ((?<=\1)|^)(?!\s*[rR]?(\'\'\'|\"\"\"|\'|\"))
     patterns:
       - include: '#docstring'
 
@@ -312,7 +316,7 @@ repository:
 
       - name: string.quoted.docstring.single.python
         begin: (\'|\")
-        end: (\1)|((?<!\\)\n)
+        end: (\1)|(\n)
         beginCaptures:
           '1': {name: punctuation.definition.string.begin.python}
         endCaptures:
@@ -324,7 +328,7 @@ repository:
 
       - name: string.quoted.docstring.raw.single.python
         begin: ([rR])(\'|\")
-        end: (\2)|((?<!\\)\n)
+        end: (\2)|(\n)
         beginCaptures:
           '1': {name: storage.type.string.python}
           '2': {name: punctuation.definition.string.begin.python}
diff --git a/grammars/src/pystring.inc.syntax.yaml b/grammars/src/pystring.inc.syntax.yaml
index 36e0bd1b..8bd53282 100644
--- a/grammars/src/pystring.inc.syntax.yaml
+++ b/grammars/src/pystring.inc.syntax.yaml
@@ -44,7 +44,7 @@ repository:
 
   string-quoted-${line}-line:
     name: string.quoted.${line}.python
-    begin: (\b[rR](?=[uU]))?([uU])?(${marker})
+    begin: (?:\b([rR])(?=[uU]))?([uU])?(${marker})
     end: (\3)${guard}
     beginCaptures:
       '1': {name: invalid.illegal.prefix.python}
diff --git a/package.json b/package.json
index 7673f4fd..6fea33e6 100644
--- a/package.json
+++ b/package.json
@@ -66,5 +66,9 @@
         "path": "./grammars/MagicPython.tmLanguage"
       }
     ]
+  },
+  "dependencies": {
+    "oniguruma": "^7.0.0",
+    "syntaxdev": "0.0.16"
   }
 }
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index c0d65218..56462323 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -2856,7 +2856,7 @@ describe("Grammar Tests", function() {
 
   it("test/docstrings/continuation2.py", 
     function() {
-      tokens = grammar.tokenizeLines("'\n'")
+      tokens = grammar.tokenizeLines("'\n'\n# comment")
       expect(tokens[0][0].value).toBe("'");
       expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[0][1].value).toBe("");
@@ -2865,6 +2865,10 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[1][1].value).toBe("");
       expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[2][0].value).toBe("#");
+      expect(tokens[2][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][1].value).toBe(" comment");
+      expect(tokens[2][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
     });
 
   it("test/docstrings/continuation3.py", 
@@ -3035,6 +3039,73 @@ describe("Grammar Tests", function() {
       expect(tokens[12][1].scopes).toEqual(["source.python","string.quoted.docstring.raw.multi.python","punctuation.definition.string.end.python"]);
     });
 
+  it("test/docstrings/continuation5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("'implicit ' \"concatenation\"\n\n'''implicit\n''' 'concatenation'\n\n'''implicit\n''' \"\"\"\nconcatenation\n\"\"\"\n\n'implicit' '''\nconcatenation\n'''")
+      expect(tokens[0][0].value).toBe("'");
+      expect(tokens[0][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].value).toBe("implicit ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[0][2].value).toBe("'");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("\"");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].value).toBe("concatenation");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[0][6].value).toBe("\"");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("'''");
+      expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][1].value).toBe("implicit");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[3][0].value).toBe("'''");
+      expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("'");
+      expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][3].value).toBe("concatenation");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[3][4].value).toBe("'");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].value).toBe("'''");
+      expect(tokens[5][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][1].value).toBe("implicit");
+      expect(tokens[5][1].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[6][0].value).toBe("'''");
+      expect(tokens[6][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].value).toBe("\"\"\"");
+      expect(tokens[6][2].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][0].value).toBe("concatenation");
+      expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[8][0].value).toBe("\"\"\"");
+      expect(tokens[8][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[9][0].value).toBe("");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][0].value).toBe("'");
+      expect(tokens[10][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][1].value).toBe("implicit");
+      expect(tokens[10][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python"]);
+      expect(tokens[10][2].value).toBe("'");
+      expect(tokens[10][2].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[10][3].value).toBe(" ");
+      expect(tokens[10][3].scopes).toEqual(["source.python"]);
+      expect(tokens[10][4].value).toBe("'''");
+      expect(tokens[10][4].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[11][0].value).toBe("concatenation");
+      expect(tokens[11][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python"]);
+      expect(tokens[12][0].value).toBe("'''");
+      expect(tokens[12][0].scopes).toEqual(["source.python","string.quoted.docstring.multi.python","punctuation.definition.string.end.python"]);
+    });
+
   it("test/docstrings/def1.py", 
     function() {
       tokens = grammar.tokenizeLines("def foo():\n    '''TE\\'''ST'''\n\ndef foo():\n    r'''TE\\'''ST'''\n\ndef foo():\n    R'''TE\\'''ST'''\n\ndef foo():\n    u'''TEST'''\n\ndef foo():\n    U'''TEST'''\n\ndef foo():\n    b'''TEST'''\n\ndef foo():\n    B'''TEST'''")
@@ -6498,7 +6569,7 @@ describe("Grammar Tests", function() {
 
   it("test/fstrings/nested3.py", 
     function() {
-      tokens = grammar.tokenizeLines("f\"result: {value:{60}.{16!s:2}{'qwerty'\n[2]}}\"")
+      tokens = grammar.tokenizeLines("f\"result: {value:{60}.{16!s:2}{'qwerty'\n[2]}}\"\n# comment")
       expect(tokens[0][0].value).toBe("f");
       expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
       expect(tokens[0][1].value).toBe("\"");
@@ -6551,6 +6622,10 @@ describe("Grammar Tests", function() {
       expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[1][5].value).toBe("");
       expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[2][0].value).toBe("#");
+      expect(tokens[2][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][1].value).toBe(" comment");
+      expect(tokens[2][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
     });
 
   it("test/fstrings/nested4.py", 
@@ -9790,7 +9865,7 @@ describe("Grammar Tests", function() {
 
   it("test/illegals/backticks3.py", 
     function() {
-      tokens = grammar.tokenizeLines("a = lambda `123`")
+      tokens = grammar.tokenizeLines("a = lambda `123`\n# comment")
       expect(tokens[0][0].value).toBe("a");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(" ");
@@ -9811,6 +9886,10 @@ describe("Grammar Tests", function() {
       expect(tokens[0][8].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","invalid.deprecated.backtick.python"]);
       expect(tokens[0][9].value).toBe("");
       expect(tokens[0][9].scopes).toEqual(["source.python","meta.lambda-function.python"]);
+      expect(tokens[1][0].value).toBe("#");
+      expect(tokens[1][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][1].value).toBe(" comment");
+      expect(tokens[1][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
     });
 
   it("test/illegals/illegal1.py", 
@@ -10951,7 +11030,7 @@ describe("Grammar Tests", function() {
 
   it("test/regexp/python2.py", 
     function() {
-      tokens = grammar.tokenizeLines("a = r'\n    (?x)\n        foo\n'")
+      tokens = grammar.tokenizeLines("a = r'\n    (?x)\n        foo\n'\n# comment")
       expect(tokens[0][0].value).toBe("a");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(" ");
@@ -10984,6 +11063,10 @@ describe("Grammar Tests", function() {
       expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[3][1].value).toBe("");
       expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.docstring.single.python","invalid.illegal.newline.python"]);
+      expect(tokens[4][0].value).toBe("#");
+      expect(tokens[4][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[4][1].value).toBe(" comment");
+      expect(tokens[4][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
     });
 
   it("test/regexp/python3.py", 
diff --git a/test/docstrings/continuation2.py b/test/docstrings/continuation2.py
index 6219f6fb..b9580e19 100644
--- a/test/docstrings/continuation2.py
+++ b/test/docstrings/continuation2.py
@@ -1,5 +1,6 @@
 '
 '
+# comment
 
 
 
@@ -7,3 +8,5 @@
               : invalid.illegal.newline.python, source.python, string.quoted.docstring.single.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.single.python
               : invalid.illegal.newline.python, source.python, string.quoted.docstring.single.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ comment      : comment.line.number-sign.python, source.python
diff --git a/test/docstrings/continuation5.py b/test/docstrings/continuation5.py
new file mode 100644
index 00000000..2e1f96ce
--- /dev/null
+++ b/test/docstrings/continuation5.py
@@ -0,0 +1,47 @@
+'implicit ' "concatenation"
+
+'''implicit
+''' 'concatenation'
+
+'''implicit
+''' """
+concatenation
+"""
+
+'implicit' '''
+concatenation
+'''
+
+
+
+'             : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.single.python
+implicit      : source.python, string.quoted.docstring.single.python
+'             : punctuation.definition.string.end.python, source.python, string.quoted.docstring.single.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.single.python
+concatenation : source.python, string.quoted.docstring.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.docstring.single.python
+              : source.python
+'''           : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.multi.python
+implicit      : source.python, string.quoted.docstring.multi.python
+'''           : punctuation.definition.string.end.python, source.python, string.quoted.docstring.multi.python
+              : source.python
+'             : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.single.python
+concatenation : source.python, string.quoted.docstring.single.python
+'             : punctuation.definition.string.end.python, source.python, string.quoted.docstring.single.python
+              : source.python
+'''           : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.multi.python
+implicit      : source.python, string.quoted.docstring.multi.python
+'''           : punctuation.definition.string.end.python, source.python, string.quoted.docstring.multi.python
+              : source.python
+"""           : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.multi.python
+concatenation : source.python, string.quoted.docstring.multi.python
+"""           : punctuation.definition.string.end.python, source.python, string.quoted.docstring.multi.python
+              : source.python
+'             : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.single.python
+implicit      : source.python, string.quoted.docstring.single.python
+'             : punctuation.definition.string.end.python, source.python, string.quoted.docstring.single.python
+              : source.python
+'''           : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.multi.python
+concatenation : source.python, string.quoted.docstring.multi.python
+'''           : punctuation.definition.string.end.python, source.python, string.quoted.docstring.multi.python
diff --git a/test/fstrings/nested3.py b/test/fstrings/nested3.py
index 607c38ca..64589b18 100644
--- a/test/fstrings/nested3.py
+++ b/test/fstrings/nested3.py
@@ -1,6 +1,6 @@
 f"result: {value:{60}.{16!s:2}{'qwerty'
 [2]}}"
-
+# comment
 
 
 
@@ -30,3 +30,5 @@
 }}            : source.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
               : invalid.illegal.newline.python, source.python, string.quoted.single.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ comment      : comment.line.number-sign.python, source.python
diff --git a/test/illegals/backticks3.py b/test/illegals/backticks3.py
index b4ae29c9..d99080e8 100644
--- a/test/illegals/backticks3.py
+++ b/test/illegals/backticks3.py
@@ -1,4 +1,5 @@
 a = lambda `123`
+# comment
 
 
 
@@ -12,3 +13,5 @@
 123           : constant.numeric.dec.python, invalid.deprecated.backtick.python, meta.function.lambda.parameters.python, meta.lambda-function.python, source.python
 `             : invalid.deprecated.backtick.python, meta.function.lambda.parameters.python, meta.lambda-function.python, source.python
               : meta.lambda-function.python, source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ comment      : comment.line.number-sign.python, source.python
diff --git a/test/regexp/python2.py b/test/regexp/python2.py
index bda2bb0b..1738c203 100644
--- a/test/regexp/python2.py
+++ b/test/regexp/python2.py
@@ -2,6 +2,7 @@
     (?x)
         foo
 '
+# comment
 
 
 
@@ -21,3 +22,5 @@
 foo           : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.single.python
               : invalid.illegal.newline.python, source.python, string.quoted.docstring.single.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ comment      : comment.line.number-sign.python, source.python

From fb56c6a98d684e30bed1b0f9647e85741a48f914 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Thu, 19 Jul 2018 15:09:02 -0400
Subject: [PATCH 34/65] Update string formatting scopes.

Add two scopes for finer control of format highlighting:
- meta.format.percent.python
- meta.format.brace.python

Issue #106.
---
 grammars/MagicPython.cson            |  59 +++++----
 grammars/MagicPython.tmLanguage      |  69 ++++++----
 grammars/src/MagicPython.syntax.yaml |  53 +++++---
 misc/scopes                          |   2 +
 test/atom-spec/python-spec.js        | 186 ++++++++++++---------------
 test/strings/format1.py              |  21 ++-
 test/strings/format10.py             |   8 +-
 test/strings/format11.py             |   4 +-
 test/strings/format12.py             |   4 +-
 test/strings/format15.py             |   4 +-
 test/strings/format2.py              |  16 +--
 test/strings/format3.py              |  14 +-
 test/strings/format4.py              |  16 +--
 test/strings/format5.py              |  17 +--
 test/strings/format6.py              |   2 +-
 test/strings/format7.py              |   4 +-
 test/strings/format9.py              |  10 +-
 17 files changed, 252 insertions(+), 237 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 8dff74fb..54ef1a3f 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -917,23 +917,28 @@ repository:
     name: "constant.language.python"
     match: "\\\\$"
   "string-formatting":
-    name: "constant.character.format.placeholder.other.python"
+    name: "meta.format.percent.python"
     match: '''
       (?x)
-        % (\\([\\w\\s]*\\))?
-          [-+#0 ]*
-          (\\d+|\\*)? (\\.(\\d+|\\*))?
-          ([hlL])?
-          [diouxXeEfFgGcrsa%]
+        (
+          % (\\([\\w\\s]*\\))?
+            [-+#0 ]*
+            (\\d+|\\*)? (\\.(\\d+|\\*))?
+            ([hlL])?
+            [diouxXeEfFgGcrsa%]
+        )
       
     '''
+    captures:
+      "1":
+        name: "constant.character.format.placeholder.other.python"
   "string-brace-formatting":
     patterns: [
       {
-        name: "constant.character.format.placeholder.other.python"
+        name: "meta.format.brace.python"
         match: '''
           (?x)
-            (?:
+            (
               {{ | }}
               | (?:
                 {
@@ -946,36 +951,38 @@ repository:
           
         '''
         captures:
-          "2":
-            name: "storage.type.format.python"
+          "1":
+            name: "constant.character.format.placeholder.other.python"
           "3":
             name: "storage.type.format.python"
+          "4":
+            name: "storage.type.format.python"
       }
       {
-        name: "constant.character.format.placeholder.other.python"
-        begin: '''
+        name: "meta.format.brace.python"
+        match: '''
           (?x)
-              \\{
+            (
+              {
                 \\w*? (\\.[[:alpha:]_]\\w*? | \\[[^\\]'"]+\\])*?
                 (![rsa])?
                 (:)
-                  (?=[^'"}\\n]*\\})
+                  (
+                    [^'"{}\\n]+?
+                    |
+                    \\{ [^'"}\\n]*? \\}
+                  )*
+              }
+            )
           
         '''
-        end: "\\}"
-        beginCaptures:
-          "2":
-            name: "storage.type.format.python"
+        captures:
+          "1":
+            name: "constant.character.format.placeholder.other.python"
           "3":
             name: "storage.type.format.python"
-        patterns: [
-          {
-            match: '''
-              (?x) \\{ [^'"}\\n]*? \\} (?=.*?\\})
-              
-            '''
-          }
-        ]
+          "4":
+            name: "storage.type.format.python"
       }
     ]
   "fstring-formatting":
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index de83a6bc..35d7b049 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -1411,15 +1411,25 @@
       <key>string-formatting</key>
       <dict>
         <key>name</key>
-        <string>constant.character.format.placeholder.other.python</string>
+        <string>meta.format.percent.python</string>
         <key>match</key>
         <string>(?x)
-  % (\([\w\s]*\))?
-    [-+#0 ]*
-    (\d+|\*)? (\.(\d+|\*))?
-    ([hlL])?
-    [diouxXeEfFgGcrsa%]
+  (
+    % (\([\w\s]*\))?
+      [-+#0 ]*
+      (\d+|\*)? (\.(\d+|\*))?
+      ([hlL])?
+      [diouxXeEfFgGcrsa%]
+  )
 </string>
+        <key>captures</key>
+        <dict>
+          <key>1</key>
+          <dict>
+            <key>name</key>
+            <string>constant.character.format.placeholder.other.python</string>
+          </dict>
+        </dict>
       </dict>
       <key>string-brace-formatting</key>
       <dict>
@@ -1427,10 +1437,10 @@
         <array>
           <dict>
             <key>name</key>
-            <string>constant.character.format.placeholder.other.python</string>
+            <string>meta.format.brace.python</string>
             <key>match</key>
             <string>(?x)
-  (?:
+  (
     {{ | }}
     | (?:
       {
@@ -1443,52 +1453,59 @@
 </string>
             <key>captures</key>
             <dict>
-              <key>2</key>
+              <key>1</key>
               <dict>
                 <key>name</key>
-                <string>storage.type.format.python</string>
+                <string>constant.character.format.placeholder.other.python</string>
               </dict>
               <key>3</key>
               <dict>
                 <key>name</key>
                 <string>storage.type.format.python</string>
               </dict>
+              <key>4</key>
+              <dict>
+                <key>name</key>
+                <string>storage.type.format.python</string>
+              </dict>
             </dict>
           </dict>
           <dict>
             <key>name</key>
-            <string>constant.character.format.placeholder.other.python</string>
-            <key>begin</key>
+            <string>meta.format.brace.python</string>
+            <key>match</key>
             <string>(?x)
-    \{
+  (
+    {
       \w*? (\.[[:alpha:]_]\w*? | \[[^\]'"]+\])*?
       (![rsa])?
       (:)
-        (?=[^'"}\n]*\})
+        (
+          [^'"{}\n]+?
+          |
+          \{ [^'"}\n]*? \}
+        )*
+    }
+  )
 </string>
-            <key>end</key>
-            <string>\}</string>
-            <key>beginCaptures</key>
+            <key>captures</key>
             <dict>
-              <key>2</key>
+              <key>1</key>
               <dict>
                 <key>name</key>
-                <string>storage.type.format.python</string>
+                <string>constant.character.format.placeholder.other.python</string>
               </dict>
               <key>3</key>
               <dict>
                 <key>name</key>
                 <string>storage.type.format.python</string>
               </dict>
-            </dict>
-            <key>patterns</key>
-            <array>
+              <key>4</key>
               <dict>
-                <key>match</key>
-                <string>(?x) \{ [^'"}\n]*? \} (?=.*?\})
-</string>
+                <key>name</key>
+                <string>storage.type.format.python</string>
               </dict>
-            </array>
+            </dict>
           </dict>
         </array>
       </dict>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 334e439e..cd585f2f 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -769,21 +769,25 @@ repository:
     match: \\$
 
   string-formatting:
-    name: constant.character.format.placeholder.other.python
+    name: meta.format.percent.python
     match: |
       (?x)
-        % (\([\w\s]*\))?
-          [-+#0 ]*
-          (\d+|\*)? (\.(\d+|\*))?
-          ([hlL])?
-          [diouxXeEfFgGcrsa%]
+        (
+          % (\([\w\s]*\))?
+            [-+#0 ]*
+            (\d+|\*)? (\.(\d+|\*))?
+            ([hlL])?
+            [diouxXeEfFgGcrsa%]
+        )
+    captures:
+      '1': {name: constant.character.format.placeholder.other.python}
 
   string-brace-formatting:
     patterns:
-      - name: constant.character.format.placeholder.other.python
+      - name: meta.format.brace.python
         match: |
           (?x)
-            (?:
+            (
               {{ | }}
               | (?:
                 {
@@ -801,24 +805,33 @@ repository:
           # "storage.type..." is more likely to have special
           # highlighting in any given color scheme than
           # "support.other..."
-          #
-          '2': {name: storage.type.format.python}
+          '1': {name: constant.character.format.placeholder.other.python}
           '3': {name: storage.type.format.python}
-      - name: constant.character.format.placeholder.other.python
-        begin: |
+          '4': {name: storage.type.format.python}
+
+      # The reason for 2 separate rules is to establish which one
+      # should be matched with a higher priority. The rule below is
+      # more generic, so it should be matched only if the specific one
+      # didn't.
+      - name: meta.format.brace.python
+        match: |
           (?x)
-              \{
+            (
+              {
                 \w*? (\.[[:alpha:]_]\w*? | \[[^\]'"]+\])*?
                 (![rsa])?
                 (:)
-                  (?=[^'"}\n]*\})
-        end: \}
-        beginCaptures:
-          '2': {name: storage.type.format.python}
+                  (
+                    [^'"{}\n]+?
+                    |
+                    \{ [^'"}\n]*? \}
+                  )*
+              }
+            )
+        captures:
+          '1': {name: constant.character.format.placeholder.other.python}
           '3': {name: storage.type.format.python}
-        patterns:
-          - match: |
-              (?x) \{ [^'"}\n]*? \} (?=.*?\})
+          '4': {name: storage.type.format.python}
 
   fstring-formatting:
     patterns:
diff --git a/misc/scopes b/misc/scopes
index 128a673c..fb8522c3 100644
--- a/misc/scopes
+++ b/misc/scopes
@@ -65,6 +65,8 @@ meta.backreference.regexp
 meta.character.set.regexp
 meta.class.inheritance.python
 meta.class.python
+meta.format.brace.python
+meta.format.percent.python
 meta.fstring.python
 meta.function-call.generic.python
 meta.function-call.python
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 56462323..52ccbf80 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -12998,11 +12998,11 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].value).toBe("\"");
       expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[0][5].value).toBe("{0[ ]");
-      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][6].value).toBe(":X>+10d");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[0][7].value).toBe("}");
-      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][8].value).toBe("\"");
       expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[1][0].value).toBe("a");
@@ -13016,13 +13016,13 @@ describe("Grammar Tests", function() {
       expect(tokens[1][4].value).toBe("\"");
       expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[1][5].value).toBe("{0[ ]");
-      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][6].value).toBe("!s");
-      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[1][7].value).toBe(":X>+10d");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[1][8].value).toBe("}");
-      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][9].value).toBe("\"");
       expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[2][0].value).toBe("a");
@@ -13036,21 +13036,19 @@ describe("Grammar Tests", function() {
       expect(tokens[2][4].value).toBe("\"");
       expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[2][5].value).toBe("{0[ ]");
-      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][6].value).toBe(":");
-      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
-      expect(tokens[2][7].value).toBe("Xd>+10d");
-      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[2][8].value).toBe("}");
-      expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[2][9].value).toBe("\"");
-      expect(tokens[2][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
-      expect(tokens[2][10].value).toBe(" ");
-      expect(tokens[2][10].scopes).toEqual(["source.python"]);
-      expect(tokens[2][11].value).toBe("#");
-      expect(tokens[2][11].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
-      expect(tokens[2][12].value).toBe("invalid");
-      expect(tokens[2][12].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[2][7].value).toBe("Xd>+10d}");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][8].value).toBe("\"");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][9].value).toBe(" ");
+      expect(tokens[2][9].scopes).toEqual(["source.python"]);
+      expect(tokens[2][10].value).toBe("#");
+      expect(tokens[2][10].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][11].value).toBe("invalid");
+      expect(tokens[2][11].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
     });
 
   it("test/strings/format10.py", 
@@ -13069,25 +13067,25 @@ describe("Grammar Tests", function() {
       expect(tokens[0][5].value).toBe("blah {foo-bar ");
       expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.multi.python"]);
       expect(tokens[0][6].value).toBe("%d");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.multi.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][0].value).toBe("       blah ");
       expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
       expect(tokens[1][1].value).toBe("{foo-bar ");
       expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.multi.python"]);
       expect(tokens[1][2].value).toBe("%d");
-      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.multi.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][3].value).toBe("}");
       expect(tokens[1][3].scopes).toEqual(["source.python","string.quoted.multi.python"]);
       expect(tokens[2][0].value).toBe("       blah {foo-bar ");
       expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
       expect(tokens[2][1].value).toBe("%d");
-      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.multi.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][2].value).toBe(" //insane {}}");
       expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.multi.python"]);
       expect(tokens[3][0].value).toBe("       {}blah {foo-bar ");
       expect(tokens[3][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
       expect(tokens[3][1].value).toBe("%d");
-      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","string.quoted.multi.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[3][2].value).toBe(" //insane {}}");
       expect(tokens[3][2].scopes).toEqual(["source.python","string.quoted.multi.python"]);
       expect(tokens[3][3].value).toBe("'''");
@@ -13112,7 +13110,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][6].value).toBe("\\fr");
       expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
       expect(tokens[0][7].value).toBe("{still_ok}");
-      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.raw.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.raw.multi.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][8].value).toBe("ac");
       expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
       expect(tokens[0][9].value).toBe("{m_{j \\rightarrow i}(\\mathrm{good})}");
@@ -13120,7 +13118,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].value).toBe("        {not_ok} ");
       expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python"]);
       expect(tokens[1][1].value).toBe("%d");
-      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.raw.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.raw.multi.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][0].value).toBe("'''");
       expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.raw.multi.python","punctuation.definition.string.end.python"]);
     });
@@ -13145,11 +13143,11 @@ describe("Grammar Tests", function() {
       expect(tokens[0][7].value).toBe("{m_{j \\");
       expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
       expect(tokens[0][8].value).toBe("%s");
-      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.raw.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.raw.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][9].value).toBe("rightarrow i}(\\mathrm{");
       expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
       expect(tokens[0][10].value).toBe("%s");
-      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.raw.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.raw.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][11].value).toBe("good})}{\\su%m{m_{j \\rightarrow i}}}$");
       expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
       expect(tokens[0][12].value).toBe("'");
@@ -13232,11 +13230,11 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].value).toBe("'''");
       expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.begin.python"]);
       expect(tokens[1][0].value).toBe("{{");
-      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][0].scopes).toEqual(["source.python","string.quoted.multi.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][1].value).toBe(" before detection ");
       expect(tokens[1][1].scopes).toEqual(["source.python","string.quoted.multi.python"]);
       expect(tokens[1][2].value).toBe("}}");
-      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.multi.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","string.quoted.multi.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][0].value).toBe("{# jinja comment #}");
       expect(tokens[2][0].scopes).toEqual(["source.python","string.quoted.multi.python"]);
       expect(tokens[3][0].value).toBe("{{ after detection }}");
@@ -13261,27 +13259,27 @@ describe("Grammar Tests", function() {
       expect(tokens[0][5].value).toBe("normal ");
       expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[0][6].value).toBe("{{");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][7].value).toBe(" normal ");
       expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[0][8].value).toBe("}}");
-      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][9].value).toBe(" normal ");
       expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[0][10].value).toBe("{10");
-      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][11].value).toBe("!r");
-      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[0][12].value).toBe("}");
-      expect(tokens[0][12].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][12].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][13].value).toBe(" normal ");
       expect(tokens[0][13].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[0][14].value).toBe("{fo.__add__");
-      expect(tokens[0][14].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][14].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][15].value).toBe("!s");
-      expect(tokens[0][15].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[0][15].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
       expect(tokens[0][16].value).toBe("}");
-      expect(tokens[0][16].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][16].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][17].value).toBe("\"");
       expect(tokens[0][17].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[0][18].value).toBe(".");
@@ -13314,7 +13312,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].value).toBe("'");
       expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[0][5].value).toBe("%i");
-      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][6].value).toBe("'");
       expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[0][7].value).toBe(" ");
@@ -13336,11 +13334,11 @@ describe("Grammar Tests", function() {
       expect(tokens[1][4].value).toBe("\"");
       expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[1][5].value).toBe("%(language)s");
-      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][6].value).toBe(" has ");
       expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[1][7].value).toBe("%(number)03d");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][8].value).toBe(" quote types.");
       expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[1][9].value).toBe("\"");
@@ -13358,11 +13356,11 @@ describe("Grammar Tests", function() {
       expect(tokens[2][5].value).toBe("\"");
       expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[2][6].value).toBe("%(language)s");
-      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.binary.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.binary.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][7].value).toBe(" has ");
       expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
       expect(tokens[2][8].value).toBe("%(number)03d");
-      expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.binary.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.binary.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][9].value).toBe(" quote types.");
       expect(tokens[2][9].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
       expect(tokens[2][10].value).toBe("\"");
@@ -13380,11 +13378,11 @@ describe("Grammar Tests", function() {
       expect(tokens[3][5].value).toBe("\"");
       expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.raw.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[3][6].value).toBe("%(language)s");
-      expect(tokens[3][6].scopes).toEqual(["source.python","string.quoted.raw.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.quoted.raw.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[3][7].value).toBe(" has ");
       expect(tokens[3][7].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
       expect(tokens[3][8].value).toBe("%(number)03d");
-      expect(tokens[3][8].scopes).toEqual(["source.python","string.quoted.raw.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][8].scopes).toEqual(["source.python","string.quoted.raw.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[3][9].value).toBe(" quote types.");
       expect(tokens[3][9].scopes).toEqual(["source.python","string.quoted.raw.single.python"]);
       expect(tokens[3][10].value).toBe("\"");
@@ -13407,17 +13405,15 @@ describe("Grammar Tests", function() {
       expect(tokens[0][5].value).toBe("qqq");
       expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[0][6].value).toBe("{");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][7].value).toBe(":");
-      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
-      expect(tokens[0][8].value).toBe("%Y-%m-%d %H:%M:%S");
-      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[0][9].value).toBe("}");
-      expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[0][10].value).toBe("www");
-      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.single.python"]);
-      expect(tokens[0][11].value).toBe("'");
-      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[0][8].value).toBe("%Y-%m-%d %H:%M:%S}");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][9].value).toBe("www");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][10].value).toBe("'");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[1][0].value).toBe("a");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(" ");
@@ -13431,21 +13427,15 @@ describe("Grammar Tests", function() {
       expect(tokens[1][5].value).toBe("qqq");
       expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[1][6].value).toBe("{0");
-      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][7].value).toBe(":");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
-      expect(tokens[1][8].value).toBe("{fill}");
-      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[1][9].value).toBe("{align}");
-      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[1][10].value).toBe("16");
-      expect(tokens[1][10].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[1][11].value).toBe("}");
-      expect(tokens[1][11].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[1][12].value).toBe("www");
-      expect(tokens[1][12].scopes).toEqual(["source.python","string.quoted.single.python"]);
-      expect(tokens[1][13].value).toBe("'");
-      expect(tokens[1][13].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[1][8].value).toBe("{fill}{align}16}");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][9].value).toBe("www");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][10].value).toBe("'");
+      expect(tokens[1][10].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
     });
 
   it("test/strings/format5.py", 
@@ -13464,19 +13454,15 @@ describe("Grammar Tests", function() {
       expect(tokens[0][5].value).toBe("qqq");
       expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[0][6].value).toBe("{0");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][7].value).toBe(":");
-      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
-      expect(tokens[0][8].value).toBe("{width}");
-      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[0][9].value).toBe("{base}");
-      expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[0][10].value).toBe("}");
-      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[0][11].value).toBe("www");
-      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.single.python"]);
-      expect(tokens[0][12].value).toBe("'");
-      expect(tokens[0][12].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[0][8].value).toBe("{width}{base}}");
+      expect(tokens[0][8].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][9].value).toBe("www");
+      expect(tokens[0][9].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][10].value).toBe("'");
+      expect(tokens[0][10].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[1][0].value).toBe("a");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(" ");
@@ -13490,17 +13476,15 @@ describe("Grammar Tests", function() {
       expect(tokens[1][5].value).toBe("qqq");
       expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[1][6].value).toBe("{0");
-      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][7].value).toBe(":");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
-      expect(tokens[1][8].value).toBe("$20");
-      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[1][9].value).toBe("}");
-      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
-      expect(tokens[1][10].value).toBe("www");
-      expect(tokens[1][10].scopes).toEqual(["source.python","string.quoted.single.python"]);
-      expect(tokens[1][11].value).toBe("'");
-      expect(tokens[1][11].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python","storage.type.format.python"]);
+      expect(tokens[1][8].value).toBe("$20}");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][9].value).toBe("www");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][10].value).toBe("'");
+      expect(tokens[1][10].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[2][0].value).toBe("a");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(" ");
@@ -13514,7 +13498,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][5].value).toBe("qqq");
       expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[2][6].value).toBe("{0}");
-      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][7].value).toBe("www");
       expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[2][8].value).toBe("'");
@@ -13577,7 +13561,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][11].value).toBe("h}");
       expect(tokens[2][11].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[2][12].value).toBe("{base}");
-      expect(tokens[2][12].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][12].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][13].value).toBe("}www");
       expect(tokens[2][13].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[2][14].value).toBe("'");
@@ -13616,11 +13600,11 @@ describe("Grammar Tests", function() {
       expect(tokens[3][5].value).toBe("12");
       expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[3][6].value).toBe("% o");
-      expect(tokens[3][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[3][7].value).toBe("f ");
       expect(tokens[3][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[3][8].value).toBe("%s");
-      expect(tokens[3][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][8].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[3][9].value).toBe("'");
       expect(tokens[3][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[3][10].value).toBe(" ");
@@ -13682,7 +13666,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][5].value).toBe("blah {foo-bar ");
       expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[0][6].value).toBe("%d");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][7].value).toBe("'");
       expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[1][0].value).toBe("a");
@@ -13700,7 +13684,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][6].value).toBe("{foo-bar ");
       expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[1][7].value).toBe("%d");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][8].value).toBe("}");
       expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[1][9].value).toBe("'");
@@ -13720,7 +13704,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][6].value).toBe("{foo-bar ");
       expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[2][7].value).toBe("%d");
-      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][8].value).toBe(" //insane {}}");
       expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[2][9].value).toBe("'");
@@ -13736,13 +13720,13 @@ describe("Grammar Tests", function() {
       expect(tokens[3][4].value).toBe("'");
       expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[3][5].value).toBe("{}");
-      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[3][6].value).toBe("blah ");
       expect(tokens[3][6].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[3][7].value).toBe("{foo-bar ");
       expect(tokens[3][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[3][8].value).toBe("%d");
-      expect(tokens[3][8].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][8].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[3][9].value).toBe(" //insane {}}");
       expect(tokens[3][9].scopes).toEqual(["source.python","string.quoted.single.python"]);
       expect(tokens[3][10].value).toBe("'");
diff --git a/test/strings/format1.py b/test/strings/format1.py
index b9b8e6e0..55327cae 100644
--- a/test/strings/format1.py
+++ b/test/strings/format1.py
@@ -9,29 +9,28 @@
 =             : keyword.operator.assignment.python, source.python
               : source.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
-{0[ ]         : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:X>+10d       : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
-}             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{0[ ]         : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+:X>+10d       : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, storage.type.format.python, string.quoted.single.python
+}             : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
-{0[ ]         : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-!s            : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
-:X>+10d       : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
-}             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{0[ ]         : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+!s            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, storage.type.format.python, string.quoted.single.python
+:X>+10d       : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, storage.type.format.python, string.quoted.single.python
+}             : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
-{0[ ]         : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:             : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
-Xd>+10d       : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-}             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{0[ ]         : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+:             : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, storage.type.format.python, string.quoted.single.python
+Xd>+10d}      : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
               : source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
diff --git a/test/strings/format10.py b/test/strings/format10.py
index 01f848f6..3cd456f7 100644
--- a/test/strings/format10.py
+++ b/test/strings/format10.py
@@ -11,15 +11,15 @@
               : source.python
 '''           : punctuation.definition.string.begin.python, source.python, string.quoted.multi.python
 blah {foo-bar  : source.python, string.quoted.multi.python
-%d            : constant.character.format.placeholder.other.python, source.python, string.quoted.multi.python
+%d            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.multi.python
        blah   : source.python, string.quoted.multi.python
 {foo-bar      : source.python, string.quoted.multi.python
-%d            : constant.character.format.placeholder.other.python, source.python, string.quoted.multi.python
+%d            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.multi.python
 }             : source.python, string.quoted.multi.python
        blah {foo-bar  : source.python, string.quoted.multi.python
-%d            : constant.character.format.placeholder.other.python, source.python, string.quoted.multi.python
+%d            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.multi.python
  //insane {}} : source.python, string.quoted.multi.python
        {}blah {foo-bar  : source.python, string.quoted.multi.python
-%d            : constant.character.format.placeholder.other.python, source.python, string.quoted.multi.python
+%d            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.multi.python
  //insane {}} : source.python, string.quoted.multi.python
 '''           : punctuation.definition.string.end.python, source.python, string.quoted.multi.python
diff --git a/test/strings/format11.py b/test/strings/format11.py
index c16d3fbf..358bb9f7 100644
--- a/test/strings/format11.py
+++ b/test/strings/format11.py
@@ -11,9 +11,9 @@
 R             : source.python, storage.type.string.python, string.quoted.raw.multi.python
 '''           : punctuation.definition.string.begin.python, source.python, string.quoted.raw.multi.python
 \fr           : source.python, string.quoted.raw.multi.python
-{still_ok}    : constant.character.format.placeholder.other.python, source.python, string.quoted.raw.multi.python
+{still_ok}    : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.raw.multi.python
 ac            : source.python, string.quoted.raw.multi.python
 {m_{j \rightarrow i}(\mathrm{good})} : source.python, string.quoted.raw.multi.python
         {not_ok}  : source.python, string.quoted.raw.multi.python
-%d            : constant.character.format.placeholder.other.python, source.python, string.quoted.raw.multi.python
+%d            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.raw.multi.python
 '''           : punctuation.definition.string.end.python, source.python, string.quoted.raw.multi.python
diff --git a/test/strings/format12.py b/test/strings/format12.py
index 6b9fd6fc..e370a39d 100644
--- a/test/strings/format12.py
+++ b/test/strings/format12.py
@@ -10,8 +10,8 @@
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
 $\frac        : source.python, string.quoted.raw.single.python
 {m_{j \       : source.python, string.quoted.raw.single.python
-%s            : constant.character.format.placeholder.other.python, source.python, string.quoted.raw.single.python
+%s            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.raw.single.python
 rightarrow i}(\mathrm{ : source.python, string.quoted.raw.single.python
-%s            : constant.character.format.placeholder.other.python, source.python, string.quoted.raw.single.python
+%s            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.raw.single.python
 good})}{\su%m{m_{j \rightarrow i}}}$ : source.python, string.quoted.raw.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.raw.single.python
diff --git a/test/strings/format15.py b/test/strings/format15.py
index b1f7ddfe..68743f4d 100644
--- a/test/strings/format15.py
+++ b/test/strings/format15.py
@@ -11,9 +11,9 @@
 =             : keyword.operator.assignment.python, source.python
               : source.python
 '''           : punctuation.definition.string.begin.python, source.python, string.quoted.multi.python
-{{            : constant.character.format.placeholder.other.python, source.python, string.quoted.multi.python
+{{            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.multi.python
  before detection  : source.python, string.quoted.multi.python
-}}            : constant.character.format.placeholder.other.python, source.python, string.quoted.multi.python
+}}            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.multi.python
 {# jinja comment #} : source.python, string.quoted.multi.python
 {{ after detection }} : source.python, string.quoted.multi.python
 '''           : punctuation.definition.string.end.python, source.python, string.quoted.multi.python
diff --git a/test/strings/format2.py b/test/strings/format2.py
index 41c1baed..86227776 100644
--- a/test/strings/format2.py
+++ b/test/strings/format2.py
@@ -8,17 +8,17 @@
               : source.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 normal        : source.python, string.quoted.single.python
-{{            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{{            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
  normal       : source.python, string.quoted.single.python
-}}            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+}}            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
  normal       : source.python, string.quoted.single.python
-{10           : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-!r            : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
-}             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{10           : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+!r            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, storage.type.format.python, string.quoted.single.python
+}             : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
  normal       : source.python, string.quoted.single.python
-{fo.__add__   : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-!s            : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
-}             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{fo.__add__   : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+!s            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, storage.type.format.python, string.quoted.single.python
+}             : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 .             : punctuation.separator.period.python, source.python
 format        : meta.function-call.generic.python, meta.function-call.python, source.python
diff --git a/test/strings/format3.py b/test/strings/format3.py
index b699bdff..2a63d31a 100644
--- a/test/strings/format3.py
+++ b/test/strings/format3.py
@@ -10,7 +10,7 @@
 =             : keyword.operator.assignment.python, source.python
               : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
-%i            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+%i            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
               : source.python
 %             : keyword.operator.arithmetic.python, source.python
@@ -21,9 +21,9 @@
 =             : keyword.operator.assignment.python, source.python
               : source.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
-%(language)s  : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+%(language)s  : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.single.python
  has          : source.python, string.quoted.single.python
-%(number)03d  : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+%(number)03d  : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.single.python
  quote types. : source.python, string.quoted.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
@@ -32,9 +32,9 @@
               : source.python
 b             : source.python, storage.type.string.python, string.quoted.binary.single.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.binary.single.python
-%(language)s  : constant.character.format.placeholder.other.python, source.python, string.quoted.binary.single.python
+%(language)s  : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.binary.single.python
  has          : source.python, string.quoted.binary.single.python
-%(number)03d  : constant.character.format.placeholder.other.python, source.python, string.quoted.binary.single.python
+%(number)03d  : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.binary.single.python
  quote types. : source.python, string.quoted.binary.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.binary.single.python
 a             : source.python
@@ -43,8 +43,8 @@
               : source.python
 R             : source.python, storage.type.string.python, string.quoted.raw.single.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
-%(language)s  : constant.character.format.placeholder.other.python, source.python, string.quoted.raw.single.python
+%(language)s  : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.raw.single.python
  has          : source.python, string.quoted.raw.single.python
-%(number)03d  : constant.character.format.placeholder.other.python, source.python, string.quoted.raw.single.python
+%(number)03d  : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.raw.single.python
  quote types. : source.python, string.quoted.raw.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.raw.single.python
diff --git a/test/strings/format4.py b/test/strings/format4.py
index e135cf03..4f21cd9c 100644
--- a/test/strings/format4.py
+++ b/test/strings/format4.py
@@ -10,10 +10,9 @@
               : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 qqq           : source.python, string.quoted.single.python
-{             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:             : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
-%Y-%m-%d %H:%M:%S : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-}             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{             : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+:             : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, storage.type.format.python, string.quoted.single.python
+%Y-%m-%d %H:%M:%S} : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 www           : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
@@ -22,11 +21,8 @@
               : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 qqq           : source.python, string.quoted.single.python
-{0            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:             : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
-{fill}        : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-{align}       : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-16            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-}             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{0            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+:             : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, storage.type.format.python, string.quoted.single.python
+{fill}{align}16} : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 www           : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
diff --git a/test/strings/format5.py b/test/strings/format5.py
index 0c3f6bb4..230253a3 100644
--- a/test/strings/format5.py
+++ b/test/strings/format5.py
@@ -11,11 +11,9 @@
               : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 qqq           : source.python, string.quoted.single.python
-{0            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:             : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
-{width}       : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-{base}        : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-}             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{0            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+:             : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, storage.type.format.python, string.quoted.single.python
+{width}{base}} : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 www           : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
@@ -24,10 +22,9 @@
               : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 qqq           : source.python, string.quoted.single.python
-{0            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-:             : constant.character.format.placeholder.other.python, source.python, storage.type.format.python, string.quoted.single.python
-$20           : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
-}             : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{0            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+:             : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, storage.type.format.python, string.quoted.single.python
+$20}          : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 www           : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
@@ -36,6 +33,6 @@
               : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 qqq           : source.python, string.quoted.single.python
-{0}           : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{0}           : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 www           : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
diff --git a/test/strings/format6.py b/test/strings/format6.py
index cf0ea3c7..aff1a320 100644
--- a/test/strings/format6.py
+++ b/test/strings/format6.py
@@ -31,6 +31,6 @@
               : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 h}            : source.python, string.quoted.single.python
-{base}        : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{base}        : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 }www          : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
diff --git a/test/strings/format7.py b/test/strings/format7.py
index e80e3d27..cafb5dcd 100644
--- a/test/strings/format7.py
+++ b/test/strings/format7.py
@@ -19,9 +19,9 @@
               : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 12            : source.python, string.quoted.single.python
-% o           : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+% o           : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.single.python
 f             : source.python, string.quoted.single.python
-%s            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+%s            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
               : source.python
 %             : keyword.operator.arithmetic.python, source.python
diff --git a/test/strings/format9.py b/test/strings/format9.py
index 26e5d643..1b493484 100644
--- a/test/strings/format9.py
+++ b/test/strings/format9.py
@@ -11,7 +11,7 @@
               : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 blah {foo-bar  : source.python, string.quoted.single.python
-%d            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+%d            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
               : source.python
@@ -20,7 +20,7 @@
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 blah          : source.python, string.quoted.single.python
 {foo-bar      : source.python, string.quoted.single.python
-%d            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+%d            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.single.python
 }             : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
@@ -30,7 +30,7 @@
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 blah          : source.python, string.quoted.single.python
 {foo-bar      : source.python, string.quoted.single.python
-%d            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+%d            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.single.python
  //insane {}} : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
@@ -38,9 +38,9 @@
 =             : keyword.operator.assignment.python, source.python
               : source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
-{}            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+{}            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 blah          : source.python, string.quoted.single.python
 {foo-bar      : source.python, string.quoted.single.python
-%d            : constant.character.format.placeholder.other.python, source.python, string.quoted.single.python
+%d            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.single.python
  //insane {}} : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python

From 2780782a60733a07cae933a9c70eb276751ae5fb Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Thu, 19 Jul 2018 16:32:17 -0400
Subject: [PATCH 35/65] Add '%b' as a valid percent-format (PEP 461).

Issue #125.
---
 grammars/MagicPython.cson            |  2 +-
 grammars/MagicPython.tmLanguage      |  2 +-
 grammars/src/MagicPython.syntax.yaml |  2 +-
 test/strings/format16.py             | 19 +++++++++++++++++++
 4 files changed, 22 insertions(+), 3 deletions(-)
 create mode 100644 test/strings/format16.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 54ef1a3f..e8d15954 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -925,7 +925,7 @@ repository:
             [-+#0 ]*
             (\\d+|\\*)? (\\.(\\d+|\\*))?
             ([hlL])?
-            [diouxXeEfFgGcrsa%]
+            [diouxXeEfFgGcrsab%]
         )
       
     '''
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 35d7b049..78f208b6 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -1419,7 +1419,7 @@
       [-+#0 ]*
       (\d+|\*)? (\.(\d+|\*))?
       ([hlL])?
-      [diouxXeEfFgGcrsa%]
+      [diouxXeEfFgGcrsab%]
   )
 </string>
         <key>captures</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index cd585f2f..2cd94a29 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -777,7 +777,7 @@ repository:
             [-+#0 ]*
             (\d+|\*)? (\.(\d+|\*))?
             ([hlL])?
-            [diouxXeEfFgGcrsa%]
+            [diouxXeEfFgGcrsab%]
         )
     captures:
       '1': {name: constant.character.format.placeholder.other.python}
diff --git a/test/strings/format16.py b/test/strings/format16.py
new file mode 100644
index 00000000..9b81ed31
--- /dev/null
+++ b/test/strings/format16.py
@@ -0,0 +1,19 @@
+a = b'%b' % b'foo'
+
+
+
+a             : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+b             : source.python, storage.type.string.python, string.quoted.binary.single.python
+'             : punctuation.definition.string.begin.python, source.python, string.quoted.binary.single.python
+%b            : constant.character.format.placeholder.other.python, meta.format.percent.python, source.python, string.quoted.binary.single.python
+'             : punctuation.definition.string.end.python, source.python, string.quoted.binary.single.python
+              : source.python
+%             : keyword.operator.arithmetic.python, source.python
+              : source.python
+b             : source.python, storage.type.string.python, string.quoted.binary.single.python
+'             : punctuation.definition.string.begin.python, source.python, string.quoted.binary.single.python
+foo           : source.python, string.quoted.binary.single.python
+'             : punctuation.definition.string.end.python, source.python, string.quoted.binary.single.python

From 9c874c6e4f6457ff87a18ad2a48c0f5e6c31c2d0 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Thu, 19 Jul 2018 18:14:26 -0400
Subject: [PATCH 36/65] Stop interpreting `exec` as a keyword.

Issue #134.
---
 grammars/MagicPython.cson            |  2 +-
 grammars/MagicPython.tmLanguage      |  2 +-
 grammars/src/MagicPython.syntax.yaml |  2 +-
 test/atom-spec/python-spec.js        | 60 +++++++++++++++++++++++++++-
 test/builtins/builtins1.py           |  4 +-
 test/builtins/builtins6.py           | 13 ++++++
 6 files changed, 78 insertions(+), 5 deletions(-)
 create mode 100644 test/builtins/builtins6.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index e8d15954..6bddf756 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -1845,7 +1845,7 @@ repository:
       (?x)
         \\b(
           and | as | assert | async | await | break | class | continue | def
-          | del | elif | else | except | exec | finally | for | from | global
+          | del | elif | else | except | finally | for | from | global
           | if | import | in | is | (?<=\\.)lambda | lambda(?=\\s*[\\.=])
           | nonlocal | not | or | pass | raise | return | try | while | with
           | yield
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 78f208b6..a068b281 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -2839,7 +2839,7 @@ indirectly through syntactic constructs
         <string>(?x)
   \b(
     and | as | assert | async | await | break | class | continue | def
-    | del | elif | else | except | exec | finally | for | from | global
+    | del | elif | else | except | finally | for | from | global
     | if | import | in | is | (?&lt;=\.)lambda | lambda(?=\s*[\.=])
     | nonlocal | not | or | pass | raise | return | try | while | with
     | yield
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 2cd94a29..c7b27645 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -1393,7 +1393,7 @@ repository:
       (?x)
         \b(
           and | as | assert | async | await | break | class | continue | def
-          | del | elif | else | except | exec | finally | for | from | global
+          | del | elif | else | except | finally | for | from | global
           | if | import | in | is | (?<=\.)lambda | lambda(?=\s*[\.=])
           | nonlocal | not | or | pass | raise | return | try | while | with
           | yield
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 52ccbf80..3baf4825 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -16,7 +16,7 @@ describe("Grammar Tests", function() {
 
   it("test/builtins/builtins1.py", 
     function() {
-      tokens = grammar.tokenizeLines("AttributeError ConnectionAbortedError\nPendingDeprecationWarning\nModuleNotFoundError\nSystemExit\nNotImplemented True None False Ellipsis\nWarning\nException BaseException\nsum oct abs type object print")
+      tokens = grammar.tokenizeLines("AttributeError ConnectionAbortedError\nPendingDeprecationWarning\nModuleNotFoundError\nSystemExit\nNotImplemented True None False Ellipsis\nWarning\nException BaseException\nsum oct abs type object print exec")
       expect(tokens[0][0].value).toBe("AttributeError");
       expect(tokens[0][0].scopes).toEqual(["source.python","support.type.exception.python"]);
       expect(tokens[0][1].value).toBe(" ");
@@ -77,6 +77,10 @@ describe("Grammar Tests", function() {
       expect(tokens[7][9].scopes).toEqual(["source.python"]);
       expect(tokens[7][10].value).toBe("print");
       expect(tokens[7][10].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[7][11].value).toBe(" ");
+      expect(tokens[7][11].scopes).toEqual(["source.python"]);
+      expect(tokens[7][12].value).toBe("exec");
+      expect(tokens[7][12].scopes).toEqual(["source.python","support.function.builtin.python"]);
     });
 
   it("test/builtins/builtins2.py", 
@@ -491,6 +495,25 @@ describe("Grammar Tests", function() {
       expect(tokens[5][1].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
     });
 
+  it("test/builtins/builtins6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("exec()\nexec(code_obj)")
+      expect(tokens[0][0].value).toBe("exec");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][2].value).toBe(")");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][0].value).toBe("exec");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[1][1].value).toBe("(");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][2].value).toBe("code_obj");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][3].value).toBe(")");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
   it("test/calls/call1.py", 
     function() {
       tokens = grammar.tokenizeLines("some_call(A, b, c[1], *args, FOO=lambda:{'q': 42}, **kwargs)")
@@ -13243,6 +13266,41 @@ describe("Grammar Tests", function() {
       expect(tokens[4][0].scopes).toEqual(["source.python","string.quoted.multi.python","punctuation.definition.string.end.python"]);
     });
 
+  it("test/strings/format16.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = b'%b' % b'foo'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("b");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("%b");
+      expect(tokens[0][6].scopes).toEqual(["source.python","string.quoted.binary.single.python","meta.format.percent.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe("%");
+      expect(tokens[0][9].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe("b");
+      expect(tokens[0][11].scopes).toEqual(["source.python","string.quoted.binary.single.python","storage.type.string.python"]);
+      expect(tokens[0][12].value).toBe("'");
+      expect(tokens[0][12].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][13].value).toBe("foo");
+      expect(tokens[0][13].scopes).toEqual(["source.python","string.quoted.binary.single.python"]);
+      expect(tokens[0][14].value).toBe("'");
+      expect(tokens[0][14].scopes).toEqual(["source.python","string.quoted.binary.single.python","punctuation.definition.string.end.python"]);
+    });
+
   it("test/strings/format2.py", 
     function() {
       tokens = grammar.tokenizeLines("a = \"normal {{ normal }} normal {10!r} normal {fo.__add__!s}\".format(fo=1)")
diff --git a/test/builtins/builtins1.py b/test/builtins/builtins1.py
index 03c18cd6..36866c2a 100644
--- a/test/builtins/builtins1.py
+++ b/test/builtins/builtins1.py
@@ -5,7 +5,7 @@
 NotImplemented True None False Ellipsis
 Warning
 Exception BaseException
-sum oct abs type object print
+sum oct abs type object print exec
 
 
 
@@ -39,3 +39,5 @@
 object        : source.python, support.type.python
               : source.python
 print         : source.python, support.function.builtin.python
+              : source.python
+exec          : source.python, support.function.builtin.python
diff --git a/test/builtins/builtins6.py b/test/builtins/builtins6.py
new file mode 100644
index 00000000..c110fa4a
--- /dev/null
+++ b/test/builtins/builtins6.py
@@ -0,0 +1,13 @@
+exec()
+exec(code_obj)
+
+
+
+
+exec          : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+exec          : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+code_obj      : meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python

From 7c43d1cb668f349b292356433272b42dab5de69d Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Thu, 19 Jul 2018 18:23:52 -0400
Subject: [PATCH 37/65] Fix an issue with `import` highlighting.

Issue #133.
---
 grammars/MagicPython.cson            | 24 +++++++++++------
 grammars/MagicPython.tmLanguage      | 33 ++++++++++++++++-------
 grammars/src/MagicPython.syntax.yaml | 23 ++++++++++------
 test/atom-spec/python-spec.js        | 39 ++++++++++++++++++++++++++--
 test/expressions/expr5.py            |  2 +-
 test/statements/import5.py           |  2 +-
 test/statements/import7.py           | 20 ++++++++++++++
 7 files changed, 114 insertions(+), 29 deletions(-)
 create mode 100644 test/statements/import7.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 6bddf756..879da336 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -1006,7 +1006,7 @@ repository:
       {
         match: '''
           (?x)
-            \\s* \\b(from)\\b \\s*(\\.+)\\s* (import)?
+            \\s* \\b(from) \\s*(\\.+)\\s* (import\\b)?
           
         '''
         captures:
@@ -1840,18 +1840,26 @@ repository:
       }
     ]
   "illegal-names":
-    name: "keyword.control.flow.python"
     match: '''
       (?x)
-        \\b(
-          and | as | assert | async | await | break | class | continue | def
-          | del | elif | else | except | finally | for | from | global
-          | if | import | in | is | (?<=\\.)lambda | lambda(?=\\s*[\\.=])
-          | nonlocal | not | or | pass | raise | return | try | while | with
-          | yield
+        \\b(?:
+          (
+            and | as | assert | async | await | break | class | continue | def
+            | del | elif | else | except | finally | for | from | global
+            | if | in | is | (?<=\\.)lambda | lambda(?=\\s*[\\.=])
+            | nonlocal | not | or | pass | raise | return | try | while | with
+            | yield
+          ) | (
+            import
+          )
         )\\b
       
     '''
+    captures:
+      "1":
+        name: "keyword.control.flow.python"
+      "2":
+        name: "keyword.control.import.python"
   "special-variables":
     match: '''
       (?x)
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index a068b281..90d27a30 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -1540,7 +1540,7 @@
           <dict>
             <key>match</key>
             <string>(?x)
-  \s* \b(from)\b \s*(\.+)\s* (import)?
+  \s* \b(from) \s*(\.+)\s* (import\b)?
 </string>
             <key>captures</key>
             <dict>
@@ -2833,18 +2833,33 @@ indirectly through syntactic constructs
       </dict>
       <key>illegal-names</key>
       <dict>
-        <key>name</key>
-        <string>keyword.control.flow.python</string>
         <key>match</key>
         <string>(?x)
-  \b(
-    and | as | assert | async | await | break | class | continue | def
-    | del | elif | else | except | finally | for | from | global
-    | if | import | in | is | (?&lt;=\.)lambda | lambda(?=\s*[\.=])
-    | nonlocal | not | or | pass | raise | return | try | while | with
-    | yield
+  \b(?:
+    (
+      and | as | assert | async | await | break | class | continue | def
+      | del | elif | else | except | finally | for | from | global
+      | if | in | is | (?&lt;=\.)lambda | lambda(?=\s*[\.=])
+      | nonlocal | not | or | pass | raise | return | try | while | with
+      | yield
+    ) | (
+      import
+    )
   )\b
 </string>
+        <key>captures</key>
+        <dict>
+          <key>1</key>
+          <dict>
+            <key>name</key>
+            <string>keyword.control.flow.python</string>
+          </dict>
+          <key>2</key>
+          <dict>
+            <key>name</key>
+            <string>keyword.control.import.python</string>
+          </dict>
+        </dict>
       </dict>
       <key>special-variables</key>
       <dict>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index c7b27645..1d6ea54d 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -848,7 +848,7 @@ repository:
     patterns:
       - match: |
           (?x)
-            \s* \b(from)\b \s*(\.+)\s* (import)?
+            \s* \b(from) \s*(\.+)\s* (import\b)?
         captures:
           '1': {name: keyword.control.import.python}
           '2': {name: punctuation.separator.period.python}
@@ -1388,16 +1388,23 @@ repository:
       - include: '#magic-variable-names'
 
   illegal-names:
-    name: keyword.control.flow.python
     match: |
       (?x)
-        \b(
-          and | as | assert | async | await | break | class | continue | def
-          | del | elif | else | except | finally | for | from | global
-          | if | import | in | is | (?<=\.)lambda | lambda(?=\s*[\.=])
-          | nonlocal | not | or | pass | raise | return | try | while | with
-          | yield
+        \b(?:
+          (
+            and | as | assert | async | await | break | class | continue | def
+            | del | elif | else | except | finally | for | from | global
+            | if | in | is | (?<=\.)lambda | lambda(?=\s*[\.=])
+            | nonlocal | not | or | pass | raise | return | try | while | with
+            | yield
+          ) | (
+            import
+          )
         )\b
+    captures:
+      '1': {name: keyword.control.flow.python}
+      '2': {name: keyword.control.import.python}
+
 
   special-variables:
     match: |
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 3baf4825..a14fc173 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -5825,7 +5825,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][8].value).toBe("{");
       expect(tokens[2][8].scopes).toEqual(["source.python","punctuation.definition.dict.begin.python"]);
       expect(tokens[2][9].value).toBe("import");
-      expect(tokens[2][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][9].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[2][10].value).toBe(":");
       expect(tokens[2][10].scopes).toEqual(["source.python","punctuation.separator.dict.python"]);
       expect(tokens[2][11].value).toBe(" ");
@@ -12370,7 +12370,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][1].value).toBe(".");
       expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("import");
-      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[4][0].value).toBe("");
       expect(tokens[4][0].scopes).toEqual(["source.python"]);
       expect(tokens[5][0].value).toBe("raise");
@@ -12430,6 +12430,41 @@ describe("Grammar Tests", function() {
       expect(tokens[0][6].scopes).toEqual(["source.python"]);
     });
 
+  it("test/statements/import7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("from .importing import *\nfrom importing import *")
+      expect(tokens[0][0].value).toBe("from");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe(".");
+      expect(tokens[0][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][3].value).toBe("importing");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("import");
+      expect(tokens[0][5].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe("*");
+      expect(tokens[0][7].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[1][0].value).toBe("from");
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("importing");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("import");
+      expect(tokens[1][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][5].value).toBe(" ");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe("*");
+      expect(tokens[1][6].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+    });
+
   it("test/statements/nonlocal1.py", 
     function() {
       tokens = grammar.tokenizeLines("nonlocal a, b, c")
diff --git a/test/expressions/expr5.py b/test/expressions/expr5.py
index 0e19a719..9c734c46 100644
--- a/test/expressions/expr5.py
+++ b/test/expressions/expr5.py
@@ -33,7 +33,7 @@
 :             : punctuation.separator.dict.python, source.python
               : source.python
 {             : punctuation.definition.dict.begin.python, source.python
-import        : keyword.control.flow.python, source.python
+import        : keyword.control.import.python, source.python
 :             : punctuation.separator.dict.python, source.python
               : source.python
 a             : source.python
diff --git a/test/statements/import5.py b/test/statements/import5.py
index 2df920d6..01c57822 100644
--- a/test/statements/import5.py
+++ b/test/statements/import5.py
@@ -25,7 +25,7 @@ def bar():
               : source.python
 foo           : source.python
 .             : punctuation.separator.period.python, source.python
-import        : keyword.control.flow.python, source.python
+import        : keyword.control.import.python, source.python
               : source.python
 raise         : keyword.control.flow.python, source.python
               : source.python
diff --git a/test/statements/import7.py b/test/statements/import7.py
new file mode 100644
index 00000000..7c0fd75f
--- /dev/null
+++ b/test/statements/import7.py
@@ -0,0 +1,20 @@
+from .importing import *
+from importing import *
+
+
+
+from          : keyword.control.import.python, source.python
+              : source.python
+.             : punctuation.separator.period.python, source.python
+importing     : source.python
+              : source.python
+import        : keyword.control.import.python, source.python
+              : source.python
+*             : keyword.operator.arithmetic.python, source.python
+from          : keyword.control.flow.python, source.python
+              : source.python
+importing     : source.python
+              : source.python
+import        : keyword.control.import.python, source.python
+              : source.python
+*             : keyword.operator.arithmetic.python, source.python

From ad6bd6211944a1b24c6594fa75ee3b15f60d7559 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Thu, 19 Jul 2018 19:59:08 -0400
Subject: [PATCH 38/65] Update the `*` and `**` in funciton call scopes.

Use `keyword.operator.unpacking.arguments.python` more consistently.

Issue #132.
---
 grammars/MagicPython.cson            | 22 +++-------
 grammars/MagicPython.tmLanguage      | 28 ++++---------
 grammars/src/MagicPython.syntax.yaml | 18 +++-----
 test/atom-spec/python-spec.js        | 63 +++++++++++++++++++++++++---
 test/calls/call10.py                 | 32 ++++++++++++++
 test/calls/call5.py                  |  4 +-
 test/calls/call6.py                  |  8 ++--
 7 files changed, 114 insertions(+), 61 deletions(-)
 create mode 100644 test/calls/call10.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 879da336..fbcc389f 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -1613,35 +1613,25 @@ repository:
       }
     ]
   "function-arguments":
-    begin: '''
-      (?x)
-        (?:
-          (\\()
-          (?:\\s*(\\*\\*|\\*))?
-        )
-      
-    '''
+    begin: "(\\()"
     end: "(?=\\))(?!\\)\\s*\\()"
     beginCaptures:
       "1":
         name: "punctuation.definition.arguments.begin.python"
-      "2":
-        name: "keyword.operator.unpacking.arguments.python"
     contentName: "meta.function-call.arguments.python"
     patterns: [
+      {
+        name: "punctuation.separator.arguments.python"
+        match: "(,)"
+      }
       {
         match: '''
           (?x)
-            (?:
-              (,)
-              (?:\\s*(\\*\\*|\\*))?
-            )
+            (?:(?<=[,(])|^) \\s* (\\*{1,2})
           
         '''
         captures:
           "1":
-            name: "punctuation.separator.arguments.python"
-          "2":
             name: "keyword.operator.unpacking.arguments.python"
       }
       {
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 90d27a30..6f1edd62 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -2528,12 +2528,7 @@
       <key>function-arguments</key>
       <dict>
         <key>begin</key>
-        <string>(?x)
-  (?:
-    (\()
-    (?:\s*(\*\*|\*))?
-  )
-</string>
+        <string>(\()</string>
         <key>end</key>
         <string>(?=\))(?!\)\s*\()</string>
         <key>beginCaptures</key>
@@ -2543,32 +2538,25 @@
             <key>name</key>
             <string>punctuation.definition.arguments.begin.python</string>
           </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.unpacking.arguments.python</string>
-          </dict>
         </dict>
         <key>contentName</key>
         <string>meta.function-call.arguments.python</string>
         <key>patterns</key>
         <array>
+          <dict>
+            <key>name</key>
+            <string>punctuation.separator.arguments.python</string>
+            <key>match</key>
+            <string>(,)</string>
+          </dict>
           <dict>
             <key>match</key>
             <string>(?x)
-  (?:
-    (,)
-    (?:\s*(\*\*|\*))?
-  )
+  (?:(?&lt;=[,(])|^) \s* (\*{1,2})
 </string>
             <key>captures</key>
             <dict>
               <key>1</key>
-              <dict>
-                <key>name</key>
-                <string>punctuation.separator.arguments.python</string>
-              </dict>
-              <key>2</key>
               <dict>
                 <key>name</key>
                 <string>keyword.operator.unpacking.arguments.python</string>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 1d6ea54d..556d0213 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -1219,27 +1219,19 @@ repository:
             \b ([[:alpha:]_]\w*) \b
 
   function-arguments:
-    begin: |
-      (?x)
-        (?:
-          (\()
-          (?:\s*(\*\*|\*))?
-        )
+    begin: (\()
     end: (?=\))(?!\)\s*\()
     beginCaptures:
       '1': {name: punctuation.definition.arguments.begin.python}
-      '2': {name: keyword.operator.unpacking.arguments.python}
     contentName: meta.function-call.arguments.python
     patterns:
+      - name: punctuation.separator.arguments.python
+        match: (,)
       - match: |
           (?x)
-            (?:
-              (,)
-              (?:\s*(\*\*|\*))?
-            )
+            (?:(?<=[,(])|^) \s* (\*{1,2})
         captures:
-          '1': {name: punctuation.separator.arguments.python}
-          '2': {name: keyword.operator.unpacking.arguments.python}
+          '1': {name: keyword.operator.unpacking.arguments.python}
       - include: '#lambda-incomplete'
       - include: '#illegal-names'
       - match: '\b([[:alpha:]_]\w*)\s*(=)(?!=)'
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index a14fc173..64447b31 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -589,6 +589,57 @@ describe("Grammar Tests", function() {
       expect(tokens[0][34].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
     });
 
+  it("test/calls/call10.py", 
+    function() {
+      tokens = grammar.tokenizeLines("x = foo(True,\n        3 * 4,\n        *a,\n        **bar)")
+      expect(tokens[0][0].value).toBe("x");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("foo");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][5].value).toBe("(");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][6].value).toBe("True");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.language.python"]);
+      expect(tokens[0][7].value).toBe(",");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[1][0].value).toBe("        ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][1].value).toBe("3");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][3].value).toBe("*");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[1][4].value).toBe(" ");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][5].value).toBe("4");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[1][6].value).toBe(",");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[2][0].value).toBe("        ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[2][1].value).toBe("*");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[2][2].value).toBe("a");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[2][3].value).toBe(",");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[3][0].value).toBe("        ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][1].value).toBe("**");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[3][2].value).toBe("bar");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][3].value).toBe(")");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
   it("test/calls/call2.py", 
     function() {
       tokens = grammar.tokenizeLines("foo(from=1)")
@@ -702,7 +753,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][1].value).toBe("(");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][2].value).toBe("*");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.unpacking.arguments.python"]);
       expect(tokens[0][3].value).toBe("a");
       expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[0][4].value).toBe(")");
@@ -712,7 +763,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][1].value).toBe("(");
       expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[1][2].value).toBe("**");
-      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.unpacking.arguments.python"]);
       expect(tokens[1][3].value).toBe("a");
       expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[1][4].value).toBe(")");
@@ -727,9 +778,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][1].value).toBe("(");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][2].value).toBe("  ");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[0][3].value).toBe("*");
-      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.unpacking.arguments.python"]);
       expect(tokens[0][4].value).toBe("a");
       expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[0][5].value).toBe(" ");
@@ -751,9 +802,9 @@ describe("Grammar Tests", function() {
       expect(tokens[1][1].value).toBe("(");
       expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[1][2].value).toBe("  ");
-      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[1][3].value).toBe("**");
-      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","keyword.operator.unpacking.arguments.python"]);
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.unpacking.arguments.python"]);
       expect(tokens[1][4].value).toBe("a");
       expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[1][5].value).toBe(" ");
diff --git a/test/calls/call10.py b/test/calls/call10.py
new file mode 100644
index 00000000..98b52f2d
--- /dev/null
+++ b/test/calls/call10.py
@@ -0,0 +1,32 @@
+x = foo(True,
+        3 * 4,
+        *a,
+        **bar)
+
+
+
+
+
+x             : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+foo           : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+True          : constant.language.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+3             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+*             : keyword.operator.arithmetic.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+4             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+*             : keyword.operator.unpacking.arguments.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+a             : meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+**            : keyword.operator.unpacking.arguments.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/calls/call5.py b/test/calls/call5.py
index f18470c4..4ea20afa 100644
--- a/test/calls/call5.py
+++ b/test/calls/call5.py
@@ -5,11 +5,11 @@
 
 f             : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-*             : keyword.operator.unpacking.arguments.python, meta.function-call.python, source.python
+*             : keyword.operator.unpacking.arguments.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 a             : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 f             : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-**            : keyword.operator.unpacking.arguments.python, meta.function-call.python, source.python
+**            : keyword.operator.unpacking.arguments.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 a             : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/calls/call6.py b/test/calls/call6.py
index 8cdcd6d4..afc87850 100644
--- a/test/calls/call6.py
+++ b/test/calls/call6.py
@@ -5,8 +5,8 @@
 
 f             : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-              : meta.function-call.python, source.python
-*             : keyword.operator.unpacking.arguments.python, meta.function-call.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+*             : keyword.operator.unpacking.arguments.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 a             : meta.function-call.arguments.python, meta.function-call.python, source.python
               : meta.function-call.arguments.python, meta.function-call.python, source.python
 ,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
@@ -17,8 +17,8 @@
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 f             : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-              : meta.function-call.python, source.python
-**            : keyword.operator.unpacking.arguments.python, meta.function-call.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+**            : keyword.operator.unpacking.arguments.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 a             : meta.function-call.arguments.python, meta.function-call.python, source.python
               : meta.function-call.arguments.python, meta.function-call.python, source.python
 ,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python

From cc2b832e81fc62f2d92e2f55448c5faf21a7fe0a Mon Sep 17 00:00:00 2001
From: Kyle Barron <barronk@mit.edu>
Date: Tue, 11 Sep 2018 19:54:51 -0400
Subject: [PATCH 39/65] Modify foldEndPattern

---
 settings/atom.cson | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/settings/atom.cson b/settings/atom.cson
index ef9a58d1..e66d6044 100644
--- a/settings/atom.cson
+++ b/settings/atom.cson
@@ -35,7 +35,7 @@
     'autoIndentOnPaste': false
     'softTabs': true
     'tabLength': 4
-    'foldEndPattern': '^\\s*"""\\s*$'
+    'foldEndPattern': '^\\s*\\}|^\\s*\\]|^\\s*\\)'
     'commentStart': '# '
     'increaseIndentPattern': '^\\s*(class|((async\\s+)?(def|with|for))|elif|else|except|finally|if|try|while)\\b.*:\\s*$'
     'decreaseIndentPattern': '^\\s*(elif|else|except|finally)\\b.*:'

From 1b72e04ac7fe2425e5325ddf0dfd97f73c83ea03 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Thu, 4 Oct 2018 15:56:26 -0400
Subject: [PATCH 40/65] Bugfix for an apparent infinite loop in grammar. (#163)

This is a case of semantically equivalent regex not being
computationally equivalent. The issue also relates to how negative
character classes (e.g. `[^abc]`) are treated. In the end I had to
replace something of the form `(A | B)*` with `A* (BA*)*` to avoid
grinding the regex engine to a halt.

Issue #150.
---
 grammars/MagicPython.cson            |  10 +-
 grammars/MagicPython.tmLanguage      |  10 +-
 grammars/src/MagicPython.syntax.yaml |  10 +-
 test/atom-spec/python-spec.js        | 144 +++++++++++++++++++++++++++
 test/strings/bug1.py                 |  47 +++++++++
 test/strings/bug2.py                 |  35 +++++++
 6 files changed, 238 insertions(+), 18 deletions(-)
 create mode 100644 test/strings/bug1.py
 create mode 100644 test/strings/bug2.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index fbcc389f..bb53f04c 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -942,7 +942,7 @@ repository:
               {{ | }}
               | (?:
                 {
-                  \\w*? (\\.[[:alpha:]_]\\w*? | \\[[^\\]'"]+\\])*?
+                  \\w* (\\.[[:alpha:]_]\\w* | \\[[^\\]'"]+\\])*
                   (![rsa])?
                   ( : \\w? [<>=^]? [-+ ]? \\#?
                     \\d* ,? (\\.\\d+)? [bcdeEfFgGnosxX%]? )?
@@ -964,13 +964,11 @@ repository:
           (?x)
             (
               {
-                \\w*? (\\.[[:alpha:]_]\\w*? | \\[[^\\]'"]+\\])*?
+                \\w* (\\.[[:alpha:]_]\\w* | \\[[^\\]'"]+\\])*
                 (![rsa])?
                 (:)
-                  (
-                    [^'"{}\\n]+?
-                    |
-                    \\{ [^'"}\\n]*? \\}
+                  [^'"{}\\n]* (?:
+                    \\{ [^'"}\\n]*? \\} [^'"{}\\n]*
                   )*
               }
             )
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 6f1edd62..90e33014 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -1444,7 +1444,7 @@
     {{ | }}
     | (?:
       {
-        \w*? (\.[[:alpha:]_]\w*? | \[[^\]'"]+\])*?
+        \w* (\.[[:alpha:]_]\w* | \[[^\]'"]+\])*
         (![rsa])?
         ( : \w? [&lt;&gt;=^]? [-+ ]? \#?
           \d* ,? (\.\d+)? [bcdeEfFgGnosxX%]? )?
@@ -1477,13 +1477,11 @@
             <string>(?x)
   (
     {
-      \w*? (\.[[:alpha:]_]\w*? | \[[^\]'"]+\])*?
+      \w* (\.[[:alpha:]_]\w* | \[[^\]'"]+\])*
       (![rsa])?
       (:)
-        (
-          [^'"{}\n]+?
-          |
-          \{ [^'"}\n]*? \}
+        [^'"{}\n]* (?:
+          \{ [^'"}\n]*? \} [^'"{}\n]*
         )*
     }
   )
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 556d0213..b2dc33f9 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -791,7 +791,7 @@ repository:
               {{ | }}
               | (?:
                 {
-                  \w*? (\.[[:alpha:]_]\w*? | \[[^\]'"]+\])*?
+                  \w* (\.[[:alpha:]_]\w* | \[[^\]'"]+\])*
                   (![rsa])?
                   ( : \w? [<>=^]? [-+ ]? \#?
                     \d* ,? (\.\d+)? [bcdeEfFgGnosxX%]? )?
@@ -818,13 +818,11 @@ repository:
           (?x)
             (
               {
-                \w*? (\.[[:alpha:]_]\w*? | \[[^\]'"]+\])*?
+                \w* (\.[[:alpha:]_]\w* | \[[^\]'"]+\])*
                 (![rsa])?
                 (:)
-                  (
-                    [^'"{}\n]+?
-                    |
-                    \{ [^'"}\n]*? \}
+                  [^'"{}\n]* (?:
+                    \{ [^'"}\n]*? \} [^'"{}\n]*
                   )*
               }
             )
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 64447b31..ebf9ccd7 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -12853,6 +12853,150 @@ describe("Grammar Tests", function() {
       expect(tokens[3][13].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
     });
 
+  it("test/strings/bug1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# issue 150\nrecord = {\n    \"a\": {k: str(v) for k, v in foo if \"\"}\n}")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" issue 150");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("record");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("{");
+      expect(tokens[1][4].scopes).toEqual(["source.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("\"");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("a");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][3].value).toBe("\"");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][4].value).toBe(":");
+      expect(tokens[2][4].scopes).toEqual(["source.python","punctuation.separator.dict.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("{");
+      expect(tokens[2][6].scopes).toEqual(["source.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[2][7].value).toBe("k");
+      expect(tokens[2][7].scopes).toEqual(["source.python"]);
+      expect(tokens[2][8].value).toBe(":");
+      expect(tokens[2][8].scopes).toEqual(["source.python","punctuation.separator.dict.python"]);
+      expect(tokens[2][9].value).toBe(" ");
+      expect(tokens[2][9].scopes).toEqual(["source.python"]);
+      expect(tokens[2][10].value).toBe("str");
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.function-call.python","support.type.python"]);
+      expect(tokens[2][11].value).toBe("(");
+      expect(tokens[2][11].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][12].value).toBe("v");
+      expect(tokens[2][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[2][13].value).toBe(")");
+      expect(tokens[2][13].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][14].value).toBe(" ");
+      expect(tokens[2][14].scopes).toEqual(["source.python"]);
+      expect(tokens[2][15].value).toBe("for");
+      expect(tokens[2][15].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][16].value).toBe(" ");
+      expect(tokens[2][16].scopes).toEqual(["source.python"]);
+      expect(tokens[2][17].value).toBe("k");
+      expect(tokens[2][17].scopes).toEqual(["source.python"]);
+      expect(tokens[2][18].value).toBe(",");
+      expect(tokens[2][18].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[2][19].value).toBe(" ");
+      expect(tokens[2][19].scopes).toEqual(["source.python"]);
+      expect(tokens[2][20].value).toBe("v");
+      expect(tokens[2][20].scopes).toEqual(["source.python"]);
+      expect(tokens[2][21].value).toBe(" ");
+      expect(tokens[2][21].scopes).toEqual(["source.python"]);
+      expect(tokens[2][22].value).toBe("in");
+      expect(tokens[2][22].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[2][23].value).toBe(" ");
+      expect(tokens[2][23].scopes).toEqual(["source.python"]);
+      expect(tokens[2][24].value).toBe("foo");
+      expect(tokens[2][24].scopes).toEqual(["source.python"]);
+      expect(tokens[2][25].value).toBe(" ");
+      expect(tokens[2][25].scopes).toEqual(["source.python"]);
+      expect(tokens[2][26].value).toBe("if");
+      expect(tokens[2][26].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][27].value).toBe(" ");
+      expect(tokens[2][27].scopes).toEqual(["source.python"]);
+      expect(tokens[2][28].value).toBe("\"");
+      expect(tokens[2][28].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][29].value).toBe("\"");
+      expect(tokens[2][29].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][30].value).toBe("}");
+      expect(tokens[2][30].scopes).toEqual(["source.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[3][0].value).toBe("}");
+      expect(tokens[3][0].scopes).toEqual(["source.python","punctuation.definition.dict.end.python"]);
+    });
+
+  it("test/strings/bug2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("# issue 150\ncmd = \"git-clang-format --style=\\\"{{BasedOnStyle: Google, ColumnLimit: 100, IndentWidth: 2, \" \\\n \"AlignConsecutiveAssignments: true}}\\\" {COMMIT_SHA} -- ./**/*.proto > {OUTPUT}\".format(")
+      expect(tokens[0][0].value).toBe("#");
+      expect(tokens[0][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[0][1].value).toBe(" issue 150");
+      expect(tokens[0][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[1][0].value).toBe("cmd");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("\"");
+      expect(tokens[1][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][5].value).toBe("git-clang-format --style=");
+      expect(tokens[1][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][6].value).toBe("\\\"");
+      expect(tokens[1][6].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[1][7].value).toBe("{{");
+      expect(tokens[1][7].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][8].value).toBe("BasedOnStyle: Google, ColumnLimit: 100, IndentWidth: 2, ");
+      expect(tokens[1][8].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[1][9].value).toBe("\"");
+      expect(tokens[1][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][10].value).toBe(" ");
+      expect(tokens[1][10].scopes).toEqual(["source.python"]);
+      expect(tokens[1][11].value).toBe("\\");
+      expect(tokens[1][11].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][12].value).toBe("");
+      expect(tokens[1][12].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe(" ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("\"");
+      expect(tokens[2][1].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("AlignConsecutiveAssignments: true");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][3].value).toBe("}}");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][4].value).toBe("\\\"");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.single.python","constant.character.escape.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][6].value).toBe("{COMMIT_SHA}");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][7].value).toBe(" -- ./**/*.proto > ");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][8].value).toBe("{OUTPUT}");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.single.python","meta.format.brace.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][9].value).toBe("\"");
+      expect(tokens[2][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][10].value).toBe(".");
+      expect(tokens[2][10].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][11].value).toBe("format");
+      expect(tokens[2][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[2][12].value).toBe("(");
+      expect(tokens[2][12].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+    });
+
   it("test/strings/bytes1.py", 
     function() {
       tokens = grammar.tokenizeLines("a = b\"\"\"\nmultiline \"binary\" string \\\n\n    \\xf1 \\u1234aaaa \\U1234aaaa\n\n    \\N{BLACK SPADE SUIT}\n\"\"\"")
diff --git a/test/strings/bug1.py b/test/strings/bug1.py
new file mode 100644
index 00000000..9b43c6de
--- /dev/null
+++ b/test/strings/bug1.py
@@ -0,0 +1,47 @@
+# issue 150
+record = {
+    "a": {k: str(v) for k, v in foo if ""}
+}
+
+
+
+
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ issue 150    : comment.line.number-sign.python, source.python
+record        : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+{             : punctuation.definition.dict.begin.python, source.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+a             : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+:             : punctuation.separator.dict.python, source.python
+              : source.python
+{             : punctuation.definition.dict.begin.python, source.python
+k             : source.python
+:             : punctuation.separator.dict.python, source.python
+              : source.python
+str           : meta.function-call.python, source.python, support.type.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+v             : meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+for           : keyword.control.flow.python, source.python
+              : source.python
+k             : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+v             : source.python
+              : source.python
+in            : keyword.operator.logical.python, source.python
+              : source.python
+foo           : source.python
+              : source.python
+if            : keyword.control.flow.python, source.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+}             : punctuation.definition.dict.end.python, source.python
+}             : punctuation.definition.dict.end.python, source.python
diff --git a/test/strings/bug2.py b/test/strings/bug2.py
new file mode 100644
index 00000000..0ba2bf8f
--- /dev/null
+++ b/test/strings/bug2.py
@@ -0,0 +1,35 @@
+# issue 150
+cmd = "git-clang-format --style=\"{{BasedOnStyle: Google, ColumnLimit: 100, IndentWidth: 2, " \
+ "AlignConsecutiveAssignments: true}}\" {COMMIT_SHA} -- ./**/*.proto > {OUTPUT}".format(
+
+
+
+
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ issue 150    : comment.line.number-sign.python, source.python
+cmd           : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+git-clang-format --style= : source.python, string.quoted.single.python
+\"            : constant.character.escape.python, source.python, string.quoted.single.python
+{{            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+BasedOnStyle: Google, ColumnLimit: 100, IndentWidth: 2,  : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+              : source.python
+\             : punctuation.separator.continuation.line.python, source.python
+              : source.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+AlignConsecutiveAssignments: true : source.python, string.quoted.single.python
+}}            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+\"            : constant.character.escape.python, source.python, string.quoted.single.python
+              : source.python, string.quoted.single.python
+{COMMIT_SHA}  : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+ -- ./**/*.proto >  : source.python, string.quoted.single.python
+{OUTPUT}      : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+.             : punctuation.separator.period.python, source.python
+format        : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python

From a891320d09aace152b05e8cce5cb4792f0194563 Mon Sep 17 00:00:00 2001
From: therumbler <therumbler@gmail.com>
Date: Thu, 4 Oct 2018 15:57:00 -0400
Subject: [PATCH 41/65] Changing Try-Except... snippets to be Python 3 style
 (as instead of ,) (#154)

---
 snippets/sublime/Try-Except-Else-Finally.sublime-snippet | 2 +-
 snippets/sublime/Try-Except-Else.sublime-snippet         | 2 +-
 snippets/sublime/Try-Except-Finally.sublime-snippet      | 2 +-
 snippets/sublime/Try-Except.sublime-snippet              | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/snippets/sublime/Try-Except-Else-Finally.sublime-snippet b/snippets/sublime/Try-Except-Else-Finally.sublime-snippet
index 00c41fb9..ff120922 100644
--- a/snippets/sublime/Try-Except-Else-Finally.sublime-snippet
+++ b/snippets/sublime/Try-Except-Else-Finally.sublime-snippet
@@ -1,7 +1,7 @@
 <snippet>
     <content><![CDATA[try:
 	${1:pass}
-except${2: ${3:Exception}, ${4:e}}:
+except${2: ${3:Exception} as ${4:e}}:
 	${5:raise}
 else:
 	${6:pass}
diff --git a/snippets/sublime/Try-Except-Else.sublime-snippet b/snippets/sublime/Try-Except-Else.sublime-snippet
index 6845aba6..09b385bd 100644
--- a/snippets/sublime/Try-Except-Else.sublime-snippet
+++ b/snippets/sublime/Try-Except-Else.sublime-snippet
@@ -1,7 +1,7 @@
 <snippet>
     <content><![CDATA[try:
 	${1:pass}
-except ${2:Exception}, ${3:e}:
+except ${2:Exception} as ${3:e}:
 	${4:raise $3}
 else:
 	${5:pass}]]></content>
diff --git a/snippets/sublime/Try-Except-Finally.sublime-snippet b/snippets/sublime/Try-Except-Finally.sublime-snippet
index 0ee74a40..b088cbe6 100644
--- a/snippets/sublime/Try-Except-Finally.sublime-snippet
+++ b/snippets/sublime/Try-Except-Finally.sublime-snippet
@@ -1,7 +1,7 @@
 <snippet>
     <content><![CDATA[try:
 	${1:pass}
-except ${2:Exception}, ${3:e}:
+except ${2:Exception} as ${3:e}:
 	${4:raise $3}
 finally:
 	${5:pass}]]></content>
diff --git a/snippets/sublime/Try-Except.sublime-snippet b/snippets/sublime/Try-Except.sublime-snippet
index bdf36a88..58f38d1b 100644
--- a/snippets/sublime/Try-Except.sublime-snippet
+++ b/snippets/sublime/Try-Except.sublime-snippet
@@ -1,7 +1,7 @@
 <snippet>
     <content><![CDATA[try:
 	${1:pass}
-except ${2:Exception}, ${3:e}:
+except ${2:Exception} as ${3:e}:
 	${4:raise $3}]]></content>
     <tabTrigger>try</tabTrigger>
     <scope>source.python</scope>

From 4030374b5245d2db6a338ba48d520aad481d74ee Mon Sep 17 00:00:00 2001
From: chbk <chbk.git@gmail.com>
Date: Thu, 4 Oct 2018 22:02:19 +0200
Subject: [PATCH 42/65] Tokenize `@` and `.` in decorators (#110)

* Tokenize `@` in decorators

* Tokenize periods in decorators
---
 grammars/MagicPython.cson            |  9 ++-
 grammars/MagicPython.tmLanguage      | 17 ++++-
 grammars/src/MagicPython.syntax.yaml |  7 +-
 misc/scopes                          |  1 +
 test/atom-spec/python-spec.js        | 98 ++++++++++++++--------------
 test/classes/class12.py              |  2 +-
 test/classes/class2.py               |  2 +-
 test/docstrings/regr1.py             |  2 +-
 test/functions/async1.py             |  2 +-
 test/functions/decorators1.py        | 18 ++---
 test/functions/decorators2.py        |  8 +--
 test/functions/decorators3.py        |  4 +-
 test/functions/decorators4.py        | 10 +--
 test/functions/decorators5.py        | 14 ++--
 test/functions/decorators6.py        | 20 +++---
 test/functions/decorators7.py        | 12 ++--
 test/functions/decorators8.py        |  2 +-
 test/unicode/unicode1.py             |  2 +-
 18 files changed, 126 insertions(+), 104 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index bb53f04c..71050143 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -1479,7 +1479,7 @@ repository:
     begin: '''
       (?x)
         ^\\s*
-        (@) \\s* (?=[[:alpha:]_]\\w*)
+        ((@)) \\s* (?=[[:alpha:]_]\\w*)
       
     '''
     end: '''
@@ -1493,6 +1493,8 @@ repository:
     beginCaptures:
       "1":
         name: "entity.name.function.decorator.python"
+      "2":
+        name: "punctuation.definition.decorator.python"
     endCaptures:
       "1":
         name: "punctuation.definition.arguments.end.python"
@@ -1518,9 +1520,12 @@ repository:
         name: "entity.name.function.decorator.python"
         match: '''
           (?x)
-            ([[:alpha:]_]\\w*) | \\.
+            ([[:alpha:]_]\\w*) | (\\.)
           
         '''
+        captures:
+          "2":
+            name: "punctuation.separator.period.python"
       }
       {
         include: "#line-continuation"
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 90e33014..c2990dae 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -2331,7 +2331,7 @@
         <key>begin</key>
         <string>(?x)
   ^\s*
-  (@) \s* (?=[[:alpha:]_]\w*)
+  ((@)) \s* (?=[[:alpha:]_]\w*)
 </string>
         <key>end</key>
         <string>(?x)
@@ -2347,6 +2347,11 @@
             <key>name</key>
             <string>entity.name.function.decorator.python</string>
           </dict>
+          <key>2</key>
+          <dict>
+            <key>name</key>
+            <string>punctuation.definition.decorator.python</string>
+          </dict>
         </dict>
         <key>endCaptures</key>
         <dict>
@@ -2390,8 +2395,16 @@
             <string>entity.name.function.decorator.python</string>
             <key>match</key>
             <string>(?x)
-  ([[:alpha:]_]\w*) | \.
+  ([[:alpha:]_]\w*) | (\.)
 </string>
+            <key>captures</key>
+            <dict>
+              <key>2</key>
+              <dict>
+                <key>name</key>
+                <string>punctuation.separator.period.python</string>
+              </dict>
+            </dict>
           </dict>
           <dict>
             <key>include</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index b2dc33f9..536bd32e 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -1138,7 +1138,7 @@ repository:
     begin: |
       (?x)
         ^\s*
-        (@) \s* (?=[[:alpha:]_]\w*)
+        ((@)) \s* (?=[[:alpha:]_]\w*)
     end: |
         (?x)
           ( \) )
@@ -1147,6 +1147,7 @@ repository:
           | (?=\n|\#)
     beginCaptures:
       '1': {name: entity.name.function.decorator.python}
+      '2': {name: punctuation.definition.decorator.python}
     endCaptures:
       '1': {name: punctuation.definition.arguments.end.python}
       '2': {name: invalid.illegal.decorator.python}
@@ -1162,7 +1163,9 @@ repository:
       - name: entity.name.function.decorator.python
         match: |
           (?x)
-            ([[:alpha:]_]\w*) | \.
+            ([[:alpha:]_]\w*) | (\.)
+        captures:
+          '2': {name: punctuation.separator.period.python}
       - include: '#line-continuation'
       - name: invalid.illegal.decorator.python
         match: |
diff --git a/misc/scopes b/misc/scopes
index fb8522c3..a49a024d 100644
--- a/misc/scopes
+++ b/misc/scopes
@@ -84,6 +84,7 @@ punctuation.comment.end.regexp
 punctuation.definition.arguments.begin.python
 punctuation.definition.arguments.end.python
 punctuation.definition.comment.python
+punctuation.definition.decorator.python
 punctuation.definition.dict.begin.python
 punctuation.definition.dict.end.python
 punctuation.definition.inheritance.begin.python
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index ebf9ccd7..9660b781 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -1410,7 +1410,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].value).toBe("    ");
       expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[1][1].value).toBe("@");
-      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[1][2].value).toBe("classmethod");
       expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python","support.type.python"]);
       expect(tokens[2][0].value).toBe("    ");
@@ -1729,7 +1729,7 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("@dec\n# Bar.name=... is not legal, but the test is for highlighter not breaking badly\nclass Spam(Foo.Bar, Bar.name={'very': 'odd'}):\n    pass")
       expect(tokens[0][0].value).toBe("@");
-      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[0][1].value).toBe("dec");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[1][0].value).toBe("#");
@@ -5013,7 +5013,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].value).toBe("    ");
       expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[1][1].value).toBe("@");
-      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[1][2].value).toBe("asd");
       expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[2][0].value).toBe("    ");
@@ -7823,7 +7823,7 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("@foo\nasync def foo():\n    a = 1\n    async for a, b, c in b:\n        async with b as d, c:\n            await func(a, b=1)")
       expect(tokens[0][0].value).toBe("@");
-      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[0][1].value).toBe("foo");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[1][0].value).toBe("async");
@@ -8924,7 +8924,7 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("@some_decorator # with comment\n@some.class.decorator\n@some_decorator(1)\n@some.decorator   (1, 3)\n@some_decorator(a=2, b={'q': 42}, **kwargs)\n@classmethod\ndef decorated(a): pass")
       expect(tokens[0][0].value).toBe("@");
-      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[0][1].value).toBe("some_decorator");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[0][2].value).toBe(" ");
@@ -8934,19 +8934,19 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].value).toBe(" with comment");
       expect(tokens[0][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
       expect(tokens[1][0].value).toBe("@");
-      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[1][1].value).toBe("some");
       expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[1][2].value).toBe(".");
-      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[1][3].value).toBe("class");
       expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.decorator.python","keyword.control.flow.python"]);
       expect(tokens[1][4].value).toBe(".");
-      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[1][5].value).toBe("decorator");
       expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[2][0].value).toBe("@");
-      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[2][1].value).toBe("some_decorator");
       expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[2][2].value).toBe("(");
@@ -8956,11 +8956,11 @@ describe("Grammar Tests", function() {
       expect(tokens[2][4].value).toBe(")");
       expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[3][0].value).toBe("@");
-      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[3][1].value).toBe("some");
       expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[3][2].value).toBe(".");
-      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[3][3].value).toBe("decorator");
       expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[3][4].value).toBe("   ");
@@ -8978,7 +8978,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][10].value).toBe(")");
       expect(tokens[3][10].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[4][0].value).toBe("@");
-      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[4][1].value).toBe("some_decorator");
       expect(tokens[4][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[4][2].value).toBe("(");
@@ -9024,7 +9024,7 @@ describe("Grammar Tests", function() {
       expect(tokens[4][22].value).toBe(")");
       expect(tokens[4][22].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[5][0].value).toBe("@");
-      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[5][1].value).toBe("classmethod");
       expect(tokens[5][1].scopes).toEqual(["source.python","meta.function.decorator.python","support.type.python"]);
       expect(tokens[6][0].value).toBe("def");
@@ -9051,7 +9051,7 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("@ f . bar . a . b\ndef foo(): pass")
       expect(tokens[0][0].value).toBe("@");
-      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[0][1].value).toBe(" ");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][2].value).toBe("f");
@@ -9059,7 +9059,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][3].value).toBe(" ");
       expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][4].value).toBe(".");
-      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[0][5].value).toBe(" ");
       expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][6].value).toBe("bar");
@@ -9067,7 +9067,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][7].value).toBe(" ");
       expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][8].value).toBe(".");
-      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[0][9].value).toBe(" ");
       expect(tokens[0][9].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][10].value).toBe("a");
@@ -9075,7 +9075,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][11].value).toBe(" ");
       expect(tokens[0][11].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][12].value).toBe(".");
-      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[0][13].value).toBe(" ");
       expect(tokens[0][13].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][14].value).toBe("b");
@@ -9102,7 +9102,7 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("@ f . bar (baz = 1)\ndef foo(): pass")
       expect(tokens[0][0].value).toBe("@");
-      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[0][1].value).toBe(" ");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][2].value).toBe("f");
@@ -9110,7 +9110,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][3].value).toBe(" ");
       expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][4].value).toBe(".");
-      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[0][5].value).toBe(" ");
       expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][6].value).toBe("bar");
@@ -9153,23 +9153,23 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("@a.b.c.None.z\ndef foo(): pass")
       expect(tokens[0][0].value).toBe("@");
-      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[0][1].value).toBe("a");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[0][2].value).toBe(".");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[0][3].value).toBe("b");
       expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[0][4].value).toBe(".");
-      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[0][5].value).toBe("c");
       expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[0][6].value).toBe(".");
-      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[0][7].value).toBe("None");
       expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.decorator.python","keyword.illegal.name.python"]);
       expect(tokens[0][8].value).toBe(".");
-      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[0][9].value).toBe("z");
       expect(tokens[0][9].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[1][0].value).toBe("def");
@@ -9194,11 +9194,11 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("@a. \\\n  b  .  \\\n   c.None.z \\\n    baz(q=1)\n@foo.ok\ndef foo(): pass")
       expect(tokens[0][0].value).toBe("@");
-      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[0][1].value).toBe("a");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[0][2].value).toBe(".");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[0][3].value).toBe(" ");
       expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][4].value).toBe("\\");
@@ -9212,7 +9212,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][2].value).toBe("  ");
       expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[1][3].value).toBe(".");
-      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[1][4].value).toBe("  ");
       expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[1][5].value).toBe("\\");
@@ -9224,11 +9224,11 @@ describe("Grammar Tests", function() {
       expect(tokens[2][1].value).toBe("c");
       expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[2][2].value).toBe(".");
-      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[2][3].value).toBe("None");
       expect(tokens[2][3].scopes).toEqual(["source.python","meta.function.decorator.python","keyword.illegal.name.python"]);
       expect(tokens[2][4].value).toBe(".");
-      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[2][5].value).toBe("z");
       expect(tokens[2][5].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[2][6].value).toBe(" ");
@@ -9252,11 +9252,11 @@ describe("Grammar Tests", function() {
       expect(tokens[3][6].value).toBe(")");
       expect(tokens[3][6].scopes).toEqual(["source.python","meta.function.decorator.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[4][0].value).toBe("@");
-      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[4][1].value).toBe("foo");
       expect(tokens[4][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[4][2].value).toBe(".");
-      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[4][3].value).toBe("ok");
       expect(tokens[4][3].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[5][0].value).toBe("def");
@@ -9281,11 +9281,11 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("@a.   b  .  \\\n   c.None.z(foo=BAR). \\\n       baz[1:2]\n@foo.class.bar[]\n@foo.ok '''\ndef foo(): pass")
       expect(tokens[0][0].value).toBe("@");
-      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[0][1].value).toBe("a");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[0][2].value).toBe(".");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[0][3].value).toBe("   ");
       expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][4].value).toBe("b");
@@ -9293,7 +9293,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][5].value).toBe("  ");
       expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][6].value).toBe(".");
-      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[0][7].value).toBe("  ");
       expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[0][8].value).toBe("\\");
@@ -9305,11 +9305,11 @@ describe("Grammar Tests", function() {
       expect(tokens[1][1].value).toBe("c");
       expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[1][2].value).toBe(".");
-      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[1][3].value).toBe("None");
       expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.decorator.python","keyword.illegal.name.python"]);
       expect(tokens[1][4].value).toBe(".");
-      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[1][5].value).toBe("z");
       expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[1][6].value).toBe("(");
@@ -9339,25 +9339,25 @@ describe("Grammar Tests", function() {
       expect(tokens[2][6].value).toBe("]");
       expect(tokens[2][6].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[3][0].value).toBe("@");
-      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[3][1].value).toBe("foo");
       expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[3][2].value).toBe(".");
-      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[3][3].value).toBe("class");
       expect(tokens[3][3].scopes).toEqual(["source.python","meta.function.decorator.python","keyword.control.flow.python"]);
       expect(tokens[3][4].value).toBe(".");
-      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[3][5].value).toBe("bar");
       expect(tokens[3][5].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[3][6].value).toBe("[]");
       expect(tokens[3][6].scopes).toEqual(["source.python","meta.function.decorator.python","invalid.illegal.decorator.python","invalid.illegal.decorator.python"]);
       expect(tokens[4][0].value).toBe("@");
-      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[4][1].value).toBe("foo");
       expect(tokens[4][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[4][2].value).toBe(".");
-      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.separator.period.python"]);
       expect(tokens[4][3].value).toBe("ok");
       expect(tokens[4][3].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[4][4].value).toBe(" ");
@@ -9394,13 +9394,13 @@ describe("Grammar Tests", function() {
       expect(tokens[1][1].value).toBe(" DO NOT DELETE TRAILING WHITESTAPCE IN THIS FILE");
       expect(tokens[1][1].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
       expect(tokens[2][0].value).toBe("@");
-      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[2][1].value).toBe("foo");
       expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[2][2].value).toBe("    ");
       expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[3][0].value).toBe("@");
-      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[3][1].value).toBe("foo");
       expect(tokens[3][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[3][2].value).toBe("(");
@@ -9410,13 +9410,13 @@ describe("Grammar Tests", function() {
       expect(tokens[3][4].value).toBe("    ");
       expect(tokens[3][4].scopes).toEqual(["source.python"]);
       expect(tokens[4][0].value).toBe("@");
-      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[4][1].value).toBe("bar");
       expect(tokens[4][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[4][2].value).toBe("\t");
       expect(tokens[4][2].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[5][0].value).toBe("@");
-      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[5][1].value).toBe("bar");
       expect(tokens[5][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[5][2].value).toBe("(");
@@ -9426,7 +9426,7 @@ describe("Grammar Tests", function() {
       expect(tokens[5][4].value).toBe("\t");
       expect(tokens[5][4].scopes).toEqual(["source.python"]);
       expect(tokens[6][0].value).toBe("@");
-      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[6][1].value).toBe("bar");
       expect(tokens[6][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[6][2].value).toBe("(");
@@ -9442,7 +9442,7 @@ describe("Grammar Tests", function() {
       expect(tokens[6][7].value).toBe(" legal");
       expect(tokens[6][7].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
       expect(tokens[7][0].value).toBe("@");
-      expect(tokens[7][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[7][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[7][1].value).toBe("bar");
       expect(tokens[7][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[7][2].value).toBe("(");
@@ -9475,7 +9475,7 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("@deco().abc  # SyntaxError: invalid syntax\ndef foo(): pass")
       expect(tokens[0][0].value).toBe("@");
-      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[0][1].value).toBe("deco");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[0][2].value).toBe("(");
@@ -14483,7 +14483,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][0].value).toBe("    ");
       expect(tokens[2][0].scopes).toEqual(["source.python","meta.function.decorator.python"]);
       expect(tokens[2][1].value).toBe("@");
-      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python","punctuation.definition.decorator.python"]);
       expect(tokens[2][2].value).toBe("æaœ");
       expect(tokens[2][2].scopes).toEqual(["source.python","meta.function.decorator.python","entity.name.function.decorator.python"]);
       expect(tokens[3][0].value).toBe("    ");
diff --git a/test/classes/class12.py b/test/classes/class12.py
index e8b69161..e0e7fb7d 100644
--- a/test/classes/class12.py
+++ b/test/classes/class12.py
@@ -17,7 +17,7 @@ class         : meta.class.python, source.python, storage.type.class.python
 F             : entity.name.type.class.python, meta.class.python, source.python
 :             : meta.class.python, punctuation.section.class.begin.python, source.python
               : meta.function.decorator.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 classmethod   : meta.function.decorator.python, source.python, support.type.python
               : meta.function.python, source.python
 def           : meta.function.python, source.python, storage.type.function.python
diff --git a/test/classes/class2.py b/test/classes/class2.py
index 536f9258..32b5a2dc 100644
--- a/test/classes/class2.py
+++ b/test/classes/class2.py
@@ -5,7 +5,7 @@ class Spam(Foo.Bar, Bar.name={'very': 'odd'}):
 
 
 
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 dec           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
  Bar.name=... is not legal, but the test is for highlighter not breaking badly : comment.line.number-sign.python, source.python
diff --git a/test/docstrings/regr1.py b/test/docstrings/regr1.py
index 7d3d5dcc..8b5a65e9 100644
--- a/test/docstrings/regr1.py
+++ b/test/docstrings/regr1.py
@@ -8,7 +8,7 @@ def foo():
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
 :             : comment.line.number-sign.python, source.python
               : meta.function.decorator.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 asd           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.python, source.python
 def           : meta.function.python, source.python, storage.type.function.python
diff --git a/test/functions/async1.py b/test/functions/async1.py
index cb6fd70e..d6a5546b 100644
--- a/test/functions/async1.py
+++ b/test/functions/async1.py
@@ -7,7 +7,7 @@ async def foo():
 
 
 
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 foo           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 async         : meta.function.python, source.python, storage.type.function.async.python
               : meta.function.python, source.python
diff --git a/test/functions/decorators1.py b/test/functions/decorators1.py
index 6fc61aea..bf03fad0 100644
--- a/test/functions/decorators1.py
+++ b/test/functions/decorators1.py
@@ -8,25 +8,25 @@ def decorated(a): pass
 
 
 
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 some_decorator : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
  with comment : comment.line.number-sign.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 some          : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 class         : keyword.control.flow.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 decorator     : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 some_decorator : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 (             : meta.function.decorator.python, punctuation.definition.arguments.begin.python, source.python
 1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function.decorator.python, source.python
 )             : meta.function.decorator.python, punctuation.definition.arguments.end.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 some          : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 decorator     : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
 (             : meta.function.decorator.python, punctuation.definition.arguments.begin.python, source.python
@@ -35,7 +35,7 @@ class         : keyword.control.flow.python, meta.function.decorator.python, sou
               : meta.function-call.arguments.python, meta.function.decorator.python, source.python
 3             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function.decorator.python, source.python
 )             : meta.function.decorator.python, punctuation.definition.arguments.end.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 some_decorator : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 (             : meta.function.decorator.python, punctuation.definition.arguments.begin.python, source.python
 a             : meta.function-call.arguments.python, meta.function.decorator.python, source.python, variable.parameter.function-call.python
@@ -58,7 +58,7 @@ class         : keyword.control.flow.python, meta.function.decorator.python, sou
 **            : keyword.operator.unpacking.arguments.python, meta.function-call.arguments.python, meta.function.decorator.python, source.python
 kwargs        : meta.function-call.arguments.python, meta.function.decorator.python, source.python
 )             : meta.function.decorator.python, punctuation.definition.arguments.end.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 classmethod   : meta.function.decorator.python, source.python, support.type.python
 def           : meta.function.python, source.python, storage.type.function.python
               : meta.function.python, source.python
diff --git a/test/functions/decorators2.py b/test/functions/decorators2.py
index af5d7170..0b129649 100644
--- a/test/functions/decorators2.py
+++ b/test/functions/decorators2.py
@@ -3,19 +3,19 @@ def foo(): pass
 
 
 
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
               : meta.function.decorator.python, source.python
 f             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
               : meta.function.decorator.python, source.python
 bar           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
               : meta.function.decorator.python, source.python
 a             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
               : meta.function.decorator.python, source.python
 b             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 def           : meta.function.python, source.python, storage.type.function.python
diff --git a/test/functions/decorators3.py b/test/functions/decorators3.py
index 0cfe7a4f..24e7a58f 100644
--- a/test/functions/decorators3.py
+++ b/test/functions/decorators3.py
@@ -3,11 +3,11 @@ def foo(): pass
 
 
 
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
               : meta.function.decorator.python, source.python
 f             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
               : meta.function.decorator.python, source.python
 bar           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
diff --git a/test/functions/decorators4.py b/test/functions/decorators4.py
index f2aab448..ba7df7bd 100644
--- a/test/functions/decorators4.py
+++ b/test/functions/decorators4.py
@@ -3,15 +3,15 @@ def foo(): pass
 
 
 
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 a             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 b             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 c             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 None          : keyword.illegal.name.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 z             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 def           : meta.function.python, source.python, storage.type.function.python
               : meta.function.python, source.python
diff --git a/test/functions/decorators5.py b/test/functions/decorators5.py
index 412747ae..436d1a4b 100644
--- a/test/functions/decorators5.py
+++ b/test/functions/decorators5.py
@@ -7,24 +7,24 @@ def foo(): pass
 
 
 
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 a             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
               : meta.function.decorator.python, source.python
 \             : meta.function.decorator.python, punctuation.separator.continuation.line.python, source.python
               : meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
 b             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
               : meta.function.decorator.python, source.python
 \             : meta.function.decorator.python, punctuation.separator.continuation.line.python, source.python
               : meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
 c             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 None          : keyword.illegal.name.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 z             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
 \             : meta.function.decorator.python, punctuation.separator.continuation.line.python, source.python
@@ -36,9 +36,9 @@ def foo(): pass
 =             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function.decorator.python, source.python
 1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function.decorator.python, source.python
 )             : meta.function.decorator.python, punctuation.definition.arguments.end.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 foo           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 ok            : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 def           : meta.function.python, source.python, storage.type.function.python
               : meta.function.python, source.python
diff --git a/test/functions/decorators6.py b/test/functions/decorators6.py
index 53264a2e..8a167cad 100644
--- a/test/functions/decorators6.py
+++ b/test/functions/decorators6.py
@@ -6,21 +6,21 @@
 def foo(): pass
 
 
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 a             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
               : meta.function.decorator.python, source.python
 b             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
               : meta.function.decorator.python, source.python
 \             : meta.function.decorator.python, punctuation.separator.continuation.line.python, source.python
               : meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
 c             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 None          : keyword.illegal.name.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 z             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 (             : meta.function.decorator.python, punctuation.definition.arguments.begin.python, source.python
 foo           : meta.function-call.arguments.python, meta.function.decorator.python, source.python, variable.parameter.function-call.python
@@ -35,16 +35,16 @@ def foo(): pass
 :             : meta.item-access.arguments.python, meta.item-access.python, punctuation.separator.slice.python, source.python
 2             : constant.numeric.dec.python, meta.item-access.arguments.python, meta.item-access.python, source.python
 ]             : meta.item-access.python, punctuation.definition.arguments.end.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 foo           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 class         : keyword.control.flow.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 bar           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 []            : invalid.illegal.decorator.python, meta.function.decorator.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 foo           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
-.             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+.             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
 ok            : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : invalid.illegal.decorator.python, meta.function.decorator.python, source.python
 '''           : invalid.illegal.decorator.python, meta.function.decorator.python, source.python
diff --git a/test/functions/decorators7.py b/test/functions/decorators7.py
index 19d3f3bd..c604f818 100644
--- a/test/functions/decorators7.py
+++ b/test/functions/decorators7.py
@@ -16,23 +16,23 @@ def baz(): pass
  this is testing trailing whitespace after the decorator : comment.line.number-sign.python, source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
  DO NOT DELETE TRAILING WHITESTAPCE IN THIS FILE : comment.line.number-sign.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 foo           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.decorator.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 foo           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 (             : meta.function.decorator.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function.decorator.python, punctuation.definition.arguments.end.python, source.python
               : source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 bar           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 	             : meta.function.decorator.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 bar           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 (             : meta.function.decorator.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function.decorator.python, punctuation.definition.arguments.end.python, source.python
 	             : source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 bar           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 (             : meta.function.decorator.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function.decorator.python, punctuation.definition.arguments.end.python, source.python
@@ -40,7 +40,7 @@ def baz(): pass
               : source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
  legal        : comment.line.number-sign.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 bar           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 (             : meta.function.decorator.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function.decorator.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/functions/decorators8.py b/test/functions/decorators8.py
index f3898789..aeb2454e 100644
--- a/test/functions/decorators8.py
+++ b/test/functions/decorators8.py
@@ -3,7 +3,7 @@ def foo(): pass
 
 
 
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 deco          : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 (             : meta.function.decorator.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function.decorator.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/unicode/unicode1.py b/test/unicode/unicode1.py
index 9d853df6..795a2645 100644
--- a/test/unicode/unicode1.py
+++ b/test/unicode/unicode1.py
@@ -24,7 +24,7 @@ class         : meta.class.python, source.python, storage.type.class.python
 Ń             : source.python, string.quoted.docstring.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.docstring.single.python
               : meta.function.decorator.python, source.python
-@             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
+@             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 æaœ           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
               : meta.function.python, source.python
 def           : meta.function.python, source.python, storage.type.function.python

From 954029739a65d662b6381dae731bea5668907c59 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Thu, 4 Oct 2018 17:09:28 -0400
Subject: [PATCH 43/65] Add support for new Python 3.7 attrs/builtins

Fixes #151 and #126
---
 .gitignore                           |  2 +-
 grammars/MagicPython.cson            | 10 ++++----
 grammars/MagicPython.tmLanguage      | 10 ++++----
 grammars/src/MagicPython.syntax.yaml | 10 ++++----
 test/atom-spec/python-spec.js        | 36 ++++++++++++++++++++++++++++
 test/builtins/builtins7.py           |  8 +++++++
 test/expressions/special2.py         | 16 +++++++++++++
 7 files changed, 76 insertions(+), 16 deletions(-)
 create mode 100644 test/builtins/builtins7.py
 create mode 100644 test/expressions/special2.py

diff --git a/.gitignore b/.gitignore
index 4377bfda..e17b261b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,4 @@ node_modules
 .DS_Store
 *.cache
 *.pyc
-
+package-lock.json
diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 71050143..c3f182d4 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -1729,7 +1729,7 @@ repository:
         match: '''
           (?x)
             (?<!\\.) \\b(
-              __import__ | abs | all | any | ascii | bin | callable
+              __import__ | abs | all | any | ascii | bin | breakpoint | callable
               | chr | compile | copyright | credits | delattr | dir | divmod
               | enumerate | eval | exec | exit | filter | format | getattr
               | globals | hasattr | hash | help | hex | id | input
@@ -1810,10 +1810,10 @@ repository:
       (?x)
         \\b(
           __(?:
-            all | bases | builtins | class | code | debug | defaults | dict
-            | doc | file | func | kwdefaults | members
-            | metaclass | methods | module | mro | name
-            | qualname | self | signature | slots | subclasses
+            all | bases | builtins | class | class_getitem | code | debug
+            | defaults | dict | doc | file | func | kwdefaults | members
+            | metaclass | methods | module | mro | mro_entries | name
+            | qualname | post_init | self | signature | slots | subclasses
             | version | weakref | wrapped | annotations | classcell
             | spec | path | package | future | traceback
           )__
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index c2990dae..5a92c63d 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -2708,7 +2708,7 @@
             <key>match</key>
             <string>(?x)
   (?&lt;!\.) \b(
-    __import__ | abs | all | any | ascii | bin | callable
+    __import__ | abs | all | any | ascii | bin | breakpoint | callable
     | chr | compile | copyright | credits | delattr | dir | divmod
     | enumerate | eval | exec | exit | filter | format | getattr
     | globals | hasattr | hash | help | hex | id | input
@@ -2798,10 +2798,10 @@ indirectly through syntactic constructs
         <string>(?x)
   \b(
     __(?:
-      all | bases | builtins | class | code | debug | defaults | dict
-      | doc | file | func | kwdefaults | members
-      | metaclass | methods | module | mro | name
-      | qualname | self | signature | slots | subclasses
+      all | bases | builtins | class | class_getitem | code | debug
+      | defaults | dict | doc | file | func | kwdefaults | members
+      | metaclass | methods | module | mro | mro_entries | name
+      | qualname | post_init | self | signature | slots | subclasses
       | version | weakref | wrapped | annotations | classcell
       | spec | path | package | future | traceback
     )__
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 536bd32e..2be48ca1 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -1294,7 +1294,7 @@ repository:
         match: |
           (?x)
             (?<!\.) \b(
-              __import__ | abs | all | any | ascii | bin | callable
+              __import__ | abs | all | any | ascii | bin | breakpoint | callable
               | chr | compile | copyright | credits | delattr | dir | divmod
               | enumerate | eval | exec | exit | filter | format | getattr
               | globals | hasattr | hash | help | hex | id | input
@@ -1364,10 +1364,10 @@ repository:
       (?x)
         \b(
           __(?:
-            all | bases | builtins | class | code | debug | defaults | dict
-            | doc | file | func | kwdefaults | members
-            | metaclass | methods | module | mro | name
-            | qualname | self | signature | slots | subclasses
+            all | bases | builtins | class | class_getitem | code | debug
+            | defaults | dict | doc | file | func | kwdefaults | members
+            | metaclass | methods | module | mro | mro_entries | name
+            | qualname | post_init | self | signature | slots | subclasses
             | version | weakref | wrapped | annotations | classcell
             | spec | path | package | future | traceback
           )__
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 9660b781..270b752b 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -514,6 +514,17 @@ describe("Grammar Tests", function() {
       expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
     });
 
+  it("test/builtins/builtins7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("breakpoint()")
+      expect(tokens[0][0].value).toBe("breakpoint");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][2].value).toBe(")");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
   it("test/calls/call1.py", 
     function() {
       tokens = grammar.tokenizeLines("some_call(A, b, c[1], *args, FOO=lambda:{'q': 42}, **kwargs)")
@@ -6177,6 +6188,31 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
     });
 
+  it("test/expressions/special2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("__post_init__\ndef __class_getitem__(): pass\n__mro_entries__")
+      expect(tokens[0][0].value).toBe("__post_init__");
+      expect(tokens[0][0].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[1][0].value).toBe("def");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[1][2].value).toBe("__class_getitem__");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","support.variable.magic.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][6].value).toBe(" ");
+      expect(tokens[1][6].scopes).toEqual(["source.python"]);
+      expect(tokens[1][7].value).toBe("pass");
+      expect(tokens[1][7].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][0].value).toBe("__mro_entries__");
+      expect(tokens[2][0].scopes).toEqual(["source.python","support.variable.magic.python"]);
+    });
+
   it("test/fstrings/comment1.py", 
     function() {
       tokens = grammar.tokenizeLines("f'prefix{10 # comment, making the string technically illegal\ndef foo(): pass")
diff --git a/test/builtins/builtins7.py b/test/builtins/builtins7.py
new file mode 100644
index 00000000..eb02d7fb
--- /dev/null
+++ b/test/builtins/builtins7.py
@@ -0,0 +1,8 @@
+breakpoint()
+
+
+
+
+breakpoint    : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/expressions/special2.py b/test/expressions/special2.py
new file mode 100644
index 00000000..2f360985
--- /dev/null
+++ b/test/expressions/special2.py
@@ -0,0 +1,16 @@
+__post_init__
+def __class_getitem__(): pass
+__mro_entries__
+
+
+
+__post_init__ : source.python, support.variable.magic.python
+def           : meta.function.python, source.python, storage.type.function.python
+              : meta.function.python, source.python
+__class_getitem__ : meta.function.python, source.python, support.variable.magic.python
+(             : meta.function.parameters.python, meta.function.python, punctuation.definition.parameters.begin.python, source.python
+)             : meta.function.parameters.python, meta.function.python, punctuation.definition.parameters.end.python, source.python
+:             : meta.function.python, punctuation.section.function.begin.python, source.python
+              : source.python
+pass          : keyword.control.flow.python, source.python
+__mro_entries__ : source.python, support.variable.magic.python

From c8893ca464f0fee1aa1335baf8dd8023c81f5663 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Thu, 4 Oct 2018 17:59:09 -0400
Subject: [PATCH 44/65] Prepare 1.1.0 release

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 6fea33e6..c4f12063 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "MagicPython",
-  "version": "1.0.12",
+  "version": "1.1.0",
   "engines": {
     "atom": "*",
     "node": "*",

From da6fa0793e2c85d3bf7709ff1d4f65ccf468db11 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Thu, 4 Oct 2018 18:11:18 -0400
Subject: [PATCH 45/65] package.json: deps -> dev-deps

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index c4f12063..8c2b61e8 100644
--- a/package.json
+++ b/package.json
@@ -67,7 +67,7 @@
       }
     ]
   },
-  "dependencies": {
+  "devDependencies": {
     "oniguruma": "^7.0.0",
     "syntaxdev": "0.0.16"
   }

From 1417e0873fafdaa3d6b1d40ec8ad863bfc23661e Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 5 Oct 2018 10:21:23 -0400
Subject: [PATCH 46/65] Prepare 1.1.1 release

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 8c2b61e8..f872035a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "MagicPython",
-  "version": "1.1.0",
+  "version": "1.1.1",
   "engines": {
     "atom": "*",
     "node": "*",

From ea55e27ee3813c146cfeffc05a1617ffffc7bf05 Mon Sep 17 00:00:00 2001
From: fjeicam <fjeicam@users.noreply.github.com>
Date: Sun, 21 Oct 2018 18:14:48 +0200
Subject: [PATCH 47/65] Fix comment (#167)

This PR adds missing part of a word in the comment.
---
 grammars/src/MagicPython.syntax.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 2be48ca1..be23b90a 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -736,7 +736,7 @@ repository:
       - include: '#impossible'
 
   f-expression:
-    comment: All valid Python expressions, except comments and line cont
+    comment: All valid Python expressions, except comments and line continuation
     patterns:
       - include: '#expression-bare'
       - include: '#member-access'

From 8ff35b3e5fcde471fae62a57ea1ae1c7cd34c9fc Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@magic.io>
Date: Sun, 21 Oct 2018 12:16:47 -0400
Subject: [PATCH 48/65] Scope `from`, `import`, and `as` the same way in
 imports. (#165)

Use `keyword.control.import.python` scope for `from`, `import`, and `as`
keywords when they appear as part of an import statement.
Use `keyword.control.flow.python` scope for `from` and `as` if they
appear elsewhere.

Issue: #123.
---
 grammars/MagicPython.cson            |  64 +++++--
 grammars/MagicPython.tmLanguage      |  82 +++++++--
 grammars/src/MagicPython.syntax.yaml |  46 +++--
 test/atom-spec/python-spec.js        | 261 ++++++++++++++++++++++++++-
 test/expressions/keywords.py         |   4 +-
 test/statements/from1.py             |  33 ++++
 test/statements/import1.py           |   4 +-
 test/statements/import6.py           |   2 +-
 test/statements/import7.py           |   2 +-
 test/statements/import8.py           |  48 +++++
 test/statements/import9.py           |  67 +++++++
 11 files changed, 557 insertions(+), 56 deletions(-)
 create mode 100644 test/statements/from1.py
 create mode 100644 test/statements/import8.py
 create mode 100644 test/statements/import9.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index c3f182d4..d04da619 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -259,12 +259,32 @@ repository:
         name: "storage.type.function.python"
         match: "\\b((async\\s+)?\\s*def)\\b"
       }
+      {
+        name: "keyword.control.flow.python"
+        comment: '''
+          if `as` is eventually followed by `:` or line continuation
+          it's probably control flow like:
+              with foo as bar, \\
+                   Foo as Bar:
+                try:
+                  do_stuff()
+                except Exception as e:
+                  pass
+          
+        '''
+        match: "\\b(?<!\\.)as\\b(?=.*[:\\\\])"
+      }
+      {
+        name: "keyword.control.import.python"
+        comment: "other legal use of `as` is in an import"
+        match: "\\b(?<!\\.)as\\b"
+      }
       {
         name: "keyword.control.flow.python"
         match: '''
           (?x)
             \\b(?<!\\.)(
-              as | async | continue | del | assert | break | finally | for
+              async | continue | del | assert | break | finally | for
               | from | elif | else | if | except | pass | raise
               | return | try | while | with
             )\\b
@@ -997,27 +1017,41 @@ repository:
     match: "(}(?!}))"
   import:
     comment: '''
-      Import statements
+      Import statements used to correctly mark `from`, `import`, and `as`
       
     '''
     patterns: [
       {
-        match: '''
-          (?x)
-            \\s* \\b(from) \\s*(\\.+)\\s* (import\\b)?
-          
-        '''
-        captures:
+        begin: "\\b(?<!\\.)(from)\\b(?=.+import)"
+        end: "$|(?=import)"
+        beginCaptures:
           "1":
             name: "keyword.control.import.python"
-          "2":
+        patterns: [
+          {
             name: "punctuation.separator.period.python"
-          "3":
-            name: "keyword.control.import.python"
+            match: "\\.+"
+          }
+          {
+            include: "#expression"
+          }
+        ]
       }
       {
-        name: "keyword.control.import.python"
-        match: "\\b(?<!\\.)import\\b"
+        begin: "\\b(?<!\\.)(import)\\b"
+        end: "$"
+        beginCaptures:
+          "1":
+            name: "keyword.control.import.python"
+        patterns: [
+          {
+            name: "keyword.control.import.python"
+            match: "\\b(?<!\\.)as\\b"
+          }
+          {
+            include: "#expression"
+          }
+        ]
       }
     ]
   "class-declaration":
@@ -1837,13 +1871,13 @@ repository:
       (?x)
         \\b(?:
           (
-            and | as | assert | async | await | break | class | continue | def
+            and | assert | async | await | break | class | continue | def
             | del | elif | else | except | finally | for | from | global
             | if | in | is | (?<=\\.)lambda | lambda(?=\\s*[\\.=])
             | nonlocal | not | or | pass | raise | return | try | while | with
             | yield
           ) | (
-            import
+            as | import
           )
         )\\b
       
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 5a92c63d..7a833786 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -416,13 +416,37 @@
             <key>match</key>
             <string>\b((async\s+)?\s*def)\b</string>
           </dict>
+          <dict>
+            <key>name</key>
+            <string>keyword.control.flow.python</string>
+            <key>comment</key>
+            <string>if `as` is eventually followed by `:` or line continuation
+it's probably control flow like:
+    with foo as bar, \
+         Foo as Bar:
+      try:
+        do_stuff()
+      except Exception as e:
+        pass
+</string>
+            <key>match</key>
+            <string>\b(?&lt;!\.)as\b(?=.*[:\\])</string>
+          </dict>
+          <dict>
+            <key>name</key>
+            <string>keyword.control.import.python</string>
+            <key>comment</key>
+            <string>other legal use of `as` is in an import</string>
+            <key>match</key>
+            <string>\b(?&lt;!\.)as\b</string>
+          </dict>
           <dict>
             <key>name</key>
             <string>keyword.control.flow.python</string>
             <key>match</key>
             <string>(?x)
   \b(?&lt;!\.)(
-    as | async | continue | del | assert | break | finally | for
+    async | continue | del | assert | break | finally | for
     | from | elif | else | if | except | pass | raise
     | return | try | while | with
   )\b
@@ -1531,39 +1555,63 @@
       <key>import</key>
       <dict>
         <key>comment</key>
-        <string>Import statements
+        <string>Import statements used to correctly mark `from`, `import`, and `as`
 </string>
         <key>patterns</key>
         <array>
           <dict>
-            <key>match</key>
-            <string>(?x)
-  \s* \b(from) \s*(\.+)\s* (import\b)?
-</string>
-            <key>captures</key>
+            <key>begin</key>
+            <string>\b(?&lt;!\.)(from)\b(?=.+import)</string>
+            <key>end</key>
+            <string>$|(?=import)</string>
+            <key>beginCaptures</key>
             <dict>
               <key>1</key>
               <dict>
                 <key>name</key>
                 <string>keyword.control.import.python</string>
               </dict>
-              <key>2</key>
+            </dict>
+            <key>patterns</key>
+            <array>
               <dict>
                 <key>name</key>
                 <string>punctuation.separator.period.python</string>
+                <key>match</key>
+                <string>\.+</string>
               </dict>
-              <key>3</key>
+              <dict>
+                <key>include</key>
+                <string>#expression</string>
+              </dict>
+            </array>
+          </dict>
+          <dict>
+            <key>begin</key>
+            <string>\b(?&lt;!\.)(import)\b</string>
+            <key>end</key>
+            <string>$</string>
+            <key>beginCaptures</key>
+            <dict>
+              <key>1</key>
               <dict>
                 <key>name</key>
                 <string>keyword.control.import.python</string>
               </dict>
             </dict>
-          </dict>
-          <dict>
-            <key>name</key>
-            <string>keyword.control.import.python</string>
-            <key>match</key>
-            <string>\b(?&lt;!\.)import\b</string>
+            <key>patterns</key>
+            <array>
+              <dict>
+                <key>name</key>
+                <string>keyword.control.import.python</string>
+                <key>match</key>
+                <string>\b(?&lt;!\.)as\b</string>
+              </dict>
+              <dict>
+                <key>include</key>
+                <string>#expression</string>
+              </dict>
+            </array>
           </dict>
         </array>
       </dict>
@@ -2836,13 +2884,13 @@ indirectly through syntactic constructs
         <string>(?x)
   \b(?:
     (
-      and | as | assert | async | await | break | class | continue | def
+      and | assert | async | await | break | class | continue | def
       | del | elif | else | except | finally | for | from | global
       | if | in | is | (?&lt;=\.)lambda | lambda(?=\s*[\.=])
       | nonlocal | not | or | pass | raise | return | try | while | with
       | yield
     ) | (
-      import
+      as | import
     )
   )\b
 </string>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index be23b90a..baf73a1c 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -359,11 +359,25 @@ repository:
     patterns:
       - name: storage.type.function.python
         match: \b((async\s+)?\s*def)\b
+      - name: keyword.control.flow.python
+        comment: |
+          if `as` is eventually followed by `:` or line continuation
+          it's probably control flow like:
+              with foo as bar, \
+                   Foo as Bar:
+                try:
+                  do_stuff()
+                except Exception as e:
+                  pass
+        match: \b(?<!\.)as\b(?=.*[:\\])
+      - name: keyword.control.import.python
+        comment: other legal use of `as` is in an import
+        match: \b(?<!\.)as\b
       - name: keyword.control.flow.python
         match: |
           (?x)
             \b(?<!\.)(
-              as | async | continue | del | assert | break | finally | for
+              async | continue | del | assert | break | finally | for
               | from | elif | else | if | except | pass | raise
               | return | try | while | with
             )\b
@@ -842,17 +856,25 @@ repository:
 
   import:
     comment: |
-      Import statements
+      Import statements used to correctly mark `from`, `import`, and `as`
     patterns:
-      - match: |
-          (?x)
-            \s* \b(from) \s*(\.+)\s* (import\b)?
-        captures:
+      - begin: \b(?<!\.)(from)\b(?=.+import)
+        end: $|(?=import)
+        beginCaptures:
           '1': {name: keyword.control.import.python}
-          '2': {name: punctuation.separator.period.python}
-          '3': {name: keyword.control.import.python}
-      - name: keyword.control.import.python
-        match: \b(?<!\.)import\b
+        patterns:
+          - name: punctuation.separator.period.python
+            match: \.+
+          - include: '#expression'
+
+      - begin: \b(?<!\.)(import)\b
+        end: $
+        beginCaptures:
+          '1': {name: keyword.control.import.python}
+        patterns:
+          - name: keyword.control.import.python
+            match: \b(?<!\.)as\b
+          - include: '#expression'
 
   class-declaration:
     patterns:
@@ -1385,13 +1407,13 @@ repository:
       (?x)
         \b(?:
           (
-            and | as | assert | async | await | break | class | continue | def
+            and | assert | async | await | break | class | continue | def
             | del | elif | else | except | finally | for | from | global
             | if | in | is | (?<=\.)lambda | lambda(?=\s*[\.=])
             | nonlocal | not | or | pass | raise | return | try | while | with
             | yield
           ) | (
-            import
+            as | import
           )
         )\b
     captures:
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 270b752b..37e92940 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -6078,7 +6078,7 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("as async await continue del assert break finally for\nfrom elif else if import except pass raise\nreturn try while with\n\nnonlocal global class def")
       expect(tokens[0][0].value).toBe("as");
-      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[0][1].value).toBe(" ");
       expect(tokens[0][1].scopes).toEqual(["source.python"]);
       expect(tokens[0][2].value).toBe("async");
@@ -6112,7 +6112,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][16].value).toBe("for");
       expect(tokens[0][16].scopes).toEqual(["source.python","keyword.control.flow.python"]);
       expect(tokens[1][0].value).toBe("from");
-      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[1][1].value).toBe(" ");
       expect(tokens[1][1].scopes).toEqual(["source.python"]);
       expect(tokens[1][2].value).toBe("elif");
@@ -12119,6 +12119,63 @@ describe("Grammar Tests", function() {
       expect(tokens[3][3].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
     });
 
+  it("test/statements/from1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("from ... import foo as bar\nraise Exception('done') from exc\nyield from foo")
+      expect(tokens[0][0].value).toBe("from");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("...");
+      expect(tokens[0][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("import");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("foo");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("as");
+      expect(tokens[0][8].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("bar");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("raise");
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("Exception");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","support.type.exception.python"]);
+      expect(tokens[1][3].value).toBe("(");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][4].value).toBe("'");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][5].value).toBe("done");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[1][6].value).toBe("'");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][7].value).toBe(")");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][8].value).toBe(" ");
+      expect(tokens[1][8].scopes).toEqual(["source.python"]);
+      expect(tokens[1][9].value).toBe("from");
+      expect(tokens[1][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][10].value).toBe(" ");
+      expect(tokens[1][10].scopes).toEqual(["source.python"]);
+      expect(tokens[1][11].value).toBe("exc");
+      expect(tokens[1][11].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("yield from");
+      expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("foo");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+    });
+
   it("test/statements/global1.py", 
     function() {
       tokens = grammar.tokenizeLines("global a, b, c")
@@ -12237,7 +12294,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][8].value).toBe(" ");
       expect(tokens[0][8].scopes).toEqual(["source.python"]);
       expect(tokens[0][9].value).toBe("as");
-      expect(tokens[0][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][9].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[0][10].value).toBe(" ");
       expect(tokens[0][10].scopes).toEqual(["source.python"]);
       expect(tokens[0][11].value).toBe("spam");
@@ -12257,7 +12314,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][3].value).toBe(" ");
       expect(tokens[1][3].scopes).toEqual(["source.python"]);
       expect(tokens[1][4].value).toBe("as");
-      expect(tokens[1][4].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][4].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[1][5].value).toBe(" ");
       expect(tokens[1][5].scopes).toEqual(["source.python"]);
       expect(tokens[1][6].value).toBe("ham");
@@ -12502,7 +12559,7 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("from __future__ import generator_stop")
       expect(tokens[0][0].value).toBe("from");
-      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[0][1].value).toBe(" ");
       expect(tokens[0][1].scopes).toEqual(["source.python"]);
       expect(tokens[0][2].value).toBe("__future__");
@@ -12537,7 +12594,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][7].value).toBe("*");
       expect(tokens[0][7].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
       expect(tokens[1][0].value).toBe("from");
-      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[1][1].value).toBe(" ");
       expect(tokens[1][1].scopes).toEqual(["source.python"]);
       expect(tokens[1][2].value).toBe("importing");
@@ -12552,6 +12609,198 @@ describe("Grammar Tests", function() {
       expect(tokens[1][6].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
     });
 
+  it("test/statements/import8.py", 
+    function() {
+      tokens = grammar.tokenizeLines("try:\n    import \\\n                    time as ham, \\\n                    datetime \\\n            # XXX: comment at the end of import\nexcept Exception as exc:\n    pass")
+      expect(tokens[0][0].value).toBe("try");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(":");
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("import");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("\\");
+      expect(tokens[1][3].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][4].value).toBe("");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].value).toBe("                    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("time");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe("as");
+      expect(tokens[2][3].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[2][4].value).toBe(" ");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][5].value).toBe("ham");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe(",");
+      expect(tokens[2][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[2][7].value).toBe(" ");
+      expect(tokens[2][7].scopes).toEqual(["source.python"]);
+      expect(tokens[2][8].value).toBe("\\");
+      expect(tokens[2][8].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[2][9].value).toBe("");
+      expect(tokens[2][9].scopes).toEqual(["source.python"]);
+      expect(tokens[3][0].value).toBe("                    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("datetime");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("\\");
+      expect(tokens[3][3].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[3][4].value).toBe("");
+      expect(tokens[3][4].scopes).toEqual(["source.python"]);
+      expect(tokens[4][0].value).toBe("            ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("#");
+      expect(tokens[4][1].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[4][2].value).toBe(" ");
+      expect(tokens[4][2].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[4][3].value).toBe("XXX");
+      expect(tokens[4][3].scopes).toEqual(["source.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[4][4].value).toBe(": comment at the end of import");
+      expect(tokens[4][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[5][0].value).toBe("except");
+      expect(tokens[5][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[5][1].value).toBe(" ");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe("Exception");
+      expect(tokens[5][2].scopes).toEqual(["source.python","support.type.exception.python"]);
+      expect(tokens[5][3].value).toBe(" ");
+      expect(tokens[5][3].scopes).toEqual(["source.python"]);
+      expect(tokens[5][4].value).toBe("as");
+      expect(tokens[5][4].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[5][5].value).toBe(" ");
+      expect(tokens[5][5].scopes).toEqual(["source.python"]);
+      expect(tokens[5][6].value).toBe("exc");
+      expect(tokens[5][6].scopes).toEqual(["source.python"]);
+      expect(tokens[5][7].value).toBe(":");
+      expect(tokens[5][7].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[6][0].value).toBe("    ");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe("pass");
+      expect(tokens[6][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/statements/import9.py", 
+    function() {
+      tokens = grammar.tokenizeLines("from . . . foo import \\\n    (\n        # XXX: legal comment inside import\n        time as bar,\n        # another comment\n        baz,\n        datetime as ham\n    )\nraise Exception('!') from None")
+      expect(tokens[0][0].value).toBe("from");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe(".");
+      expect(tokens[0][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe(".");
+      expect(tokens[0][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe(".");
+      expect(tokens[0][6].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("foo");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("import");
+      expect(tokens[0][10].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[0][11].value).toBe(" ");
+      expect(tokens[0][11].scopes).toEqual(["source.python"]);
+      expect(tokens[0][12].value).toBe("\\");
+      expect(tokens[0][12].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[0][13].value).toBe("");
+      expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("(");
+      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[2][0].value).toBe("        ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("#");
+      expect(tokens[2][1].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[2][3].value).toBe("XXX");
+      expect(tokens[2][3].scopes).toEqual(["source.python","comment.line.number-sign.python","keyword.codetag.notation.python"]);
+      expect(tokens[2][4].value).toBe(": legal comment inside import");
+      expect(tokens[2][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[3][0].value).toBe("        ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("time");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("as");
+      expect(tokens[3][3].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[3][4].value).toBe(" ");
+      expect(tokens[3][4].scopes).toEqual(["source.python"]);
+      expect(tokens[3][5].value).toBe("bar");
+      expect(tokens[3][5].scopes).toEqual(["source.python"]);
+      expect(tokens[3][6].value).toBe(",");
+      expect(tokens[3][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[4][0].value).toBe("        ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("#");
+      expect(tokens[4][1].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[4][2].value).toBe(" another comment");
+      expect(tokens[4][2].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[5][0].value).toBe("        ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("baz");
+      expect(tokens[5][1].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].value).toBe(",");
+      expect(tokens[5][2].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[6][0].value).toBe("        ");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe("datetime");
+      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].value).toBe(" ");
+      expect(tokens[6][2].scopes).toEqual(["source.python"]);
+      expect(tokens[6][3].value).toBe("as");
+      expect(tokens[6][3].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[6][4].value).toBe(" ");
+      expect(tokens[6][4].scopes).toEqual(["source.python"]);
+      expect(tokens[6][5].value).toBe("ham");
+      expect(tokens[6][5].scopes).toEqual(["source.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe(")");
+      expect(tokens[7][1].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[8][0].value).toBe("raise");
+      expect(tokens[8][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[8][1].value).toBe(" ");
+      expect(tokens[8][1].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].value).toBe("Exception");
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.function-call.python","support.type.exception.python"]);
+      expect(tokens[8][3].value).toBe("(");
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[8][4].value).toBe("'");
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[8][5].value).toBe("!");
+      expect(tokens[8][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[8][6].value).toBe("'");
+      expect(tokens[8][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][7].value).toBe(")");
+      expect(tokens[8][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[8][8].value).toBe(" ");
+      expect(tokens[8][8].scopes).toEqual(["source.python"]);
+      expect(tokens[8][9].value).toBe("from");
+      expect(tokens[8][9].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[8][10].value).toBe(" ");
+      expect(tokens[8][10].scopes).toEqual(["source.python"]);
+      expect(tokens[8][11].value).toBe("None");
+      expect(tokens[8][11].scopes).toEqual(["source.python","constant.language.python"]);
+    });
+
   it("test/statements/nonlocal1.py", 
     function() {
       tokens = grammar.tokenizeLines("nonlocal a, b, c")
diff --git a/test/expressions/keywords.py b/test/expressions/keywords.py
index 82ae6521..6ff1d516 100644
--- a/test/expressions/keywords.py
+++ b/test/expressions/keywords.py
@@ -6,7 +6,7 @@
 
 
 
-as            : keyword.control.flow.python, source.python
+as            : keyword.control.import.python, source.python
               : source.python
 async         : keyword.control.flow.python, source.python
               : source.python
@@ -23,7 +23,7 @@
 finally       : keyword.control.flow.python, source.python
               : source.python
 for           : keyword.control.flow.python, source.python
-from          : keyword.control.flow.python, source.python
+from          : keyword.control.import.python, source.python
               : source.python
 elif          : keyword.control.flow.python, source.python
               : source.python
diff --git a/test/statements/from1.py b/test/statements/from1.py
new file mode 100644
index 00000000..99d3a670
--- /dev/null
+++ b/test/statements/from1.py
@@ -0,0 +1,33 @@
+from ... import foo as bar
+raise Exception('done') from exc
+yield from foo
+
+
+
+
+from          : keyword.control.import.python, source.python
+              : source.python
+...           : punctuation.separator.period.python, source.python
+              : source.python
+import        : keyword.control.import.python, source.python
+              : source.python
+foo           : source.python
+              : source.python
+as            : keyword.control.import.python, source.python
+              : source.python
+bar           : source.python
+raise         : keyword.control.flow.python, source.python
+              : source.python
+Exception     : meta.function-call.python, source.python, support.type.exception.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+'             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+done          : meta.function-call.arguments.python, meta.function-call.python, source.python, string.quoted.single.python
+'             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+from          : keyword.control.flow.python, source.python
+              : source.python
+exc           : source.python
+yield from    : keyword.control.flow.python, source.python
+              : source.python
+foo           : source.python
diff --git a/test/statements/import1.py b/test/statements/import1.py
index f41b72c5..6faca8b3 100644
--- a/test/statements/import1.py
+++ b/test/statements/import1.py
@@ -12,7 +12,7 @@
               : source.python
 bar           : source.python
               : source.python
-as            : keyword.control.flow.python, source.python
+as            : keyword.control.import.python, source.python
               : source.python
 spam          : source.python
 ,             : punctuation.separator.element.python, source.python
@@ -22,7 +22,7 @@
               : source.python
 time          : source.python
               : source.python
-as            : keyword.control.flow.python, source.python
+as            : keyword.control.import.python, source.python
               : source.python
 ham           : source.python
 ,             : punctuation.separator.element.python, source.python
diff --git a/test/statements/import6.py b/test/statements/import6.py
index 18bacd0e..a39a790e 100644
--- a/test/statements/import6.py
+++ b/test/statements/import6.py
@@ -2,7 +2,7 @@
 
 
 
-from          : keyword.control.flow.python, source.python
+from          : keyword.control.import.python, source.python
               : source.python
 __future__    : source.python, support.variable.magic.python
               : source.python
diff --git a/test/statements/import7.py b/test/statements/import7.py
index 7c0fd75f..7951802b 100644
--- a/test/statements/import7.py
+++ b/test/statements/import7.py
@@ -11,7 +11,7 @@
 import        : keyword.control.import.python, source.python
               : source.python
 *             : keyword.operator.arithmetic.python, source.python
-from          : keyword.control.flow.python, source.python
+from          : keyword.control.import.python, source.python
               : source.python
 importing     : source.python
               : source.python
diff --git a/test/statements/import8.py b/test/statements/import8.py
new file mode 100644
index 00000000..1d49bbd1
--- /dev/null
+++ b/test/statements/import8.py
@@ -0,0 +1,48 @@
+try:
+    import \
+                    time as ham, \
+                    datetime \
+            # XXX: comment at the end of import
+except Exception as exc:
+    pass
+
+
+
+
+try           : keyword.control.flow.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+import        : keyword.control.import.python, source.python
+              : source.python
+\             : punctuation.separator.continuation.line.python, source.python
+              : source.python
+                     : source.python
+time          : source.python
+              : source.python
+as            : keyword.control.import.python, source.python
+              : source.python
+ham           : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+\             : punctuation.separator.continuation.line.python, source.python
+              : source.python
+                     : source.python
+datetime      : source.python
+              : source.python
+\             : punctuation.separator.continuation.line.python, source.python
+              : source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+              : comment.line.number-sign.python, source.python
+XXX           : comment.line.number-sign.python, keyword.codetag.notation.python, source.python
+: comment at the end of import : comment.line.number-sign.python, source.python
+except        : keyword.control.flow.python, source.python
+              : source.python
+Exception     : source.python, support.type.exception.python
+              : source.python
+as            : keyword.control.flow.python, source.python
+              : source.python
+exc           : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+pass          : keyword.control.flow.python, source.python
diff --git a/test/statements/import9.py b/test/statements/import9.py
new file mode 100644
index 00000000..2fa6bfac
--- /dev/null
+++ b/test/statements/import9.py
@@ -0,0 +1,67 @@
+from . . . foo import \
+    (
+        # XXX: legal comment inside import
+        time as bar,
+        # another comment
+        baz,
+        datetime as ham
+    )
+raise Exception('!') from None
+
+
+
+
+from          : keyword.control.import.python, source.python
+              : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
+.             : punctuation.separator.period.python, source.python
+              : source.python
+foo           : source.python
+              : source.python
+import        : keyword.control.import.python, source.python
+              : source.python
+\             : punctuation.separator.continuation.line.python, source.python
+              : source.python
+              : source.python
+(             : punctuation.parenthesis.begin.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+              : comment.line.number-sign.python, source.python
+XXX           : comment.line.number-sign.python, keyword.codetag.notation.python, source.python
+: legal comment inside import : comment.line.number-sign.python, source.python
+              : source.python
+time          : source.python
+              : source.python
+as            : keyword.control.import.python, source.python
+              : source.python
+bar           : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ another comment : comment.line.number-sign.python, source.python
+              : source.python
+baz           : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+datetime      : source.python
+              : source.python
+as            : keyword.control.import.python, source.python
+              : source.python
+ham           : source.python
+              : source.python
+)             : punctuation.parenthesis.end.python, source.python
+raise         : keyword.control.flow.python, source.python
+              : source.python
+Exception     : meta.function-call.python, source.python, support.type.exception.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+'             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+!             : meta.function-call.arguments.python, meta.function-call.python, source.python, string.quoted.single.python
+'             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+from          : keyword.control.flow.python, source.python
+              : source.python
+None          : constant.language.python, source.python

From 38422d302fe0b3e7716d26ce8cd7d0b9685f3a38 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 15 Mar 2019 00:05:00 -0400
Subject: [PATCH 49/65] Upgrade syntaxdev to 0.1.0

---
 grammars/MagicPython.cson                  |   2 +-
 grammars/MagicPython.tmLanguage            |   2 +-
 grammars/src/comment.inc.syntax.yaml       |  17 +-
 grammars/src/pyfstring.inc.syntax.yaml     | 327 ++++++++++-----------
 grammars/src/pystring.inc.syntax.yaml      | 217 +++++++-------
 grammars/src/regexp-common.inc.syntax.yaml | 221 +++++++-------
 grammars/src/regexp.inc.syntax.yaml        | 313 ++++++++++----------
 grammars/src/regexp.wrapper.syntax.yaml    |  29 +-
 package.json                               |   5 +-
 9 files changed, 564 insertions(+), 569 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index d04da619..8fe447f9 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -894,7 +894,7 @@ repository:
       }
     ]
   "f-expression":
-    comment: "All valid Python expressions, except comments and line cont"
+    comment: "All valid Python expressions, except comments and line continuation"
     patterns: [
       {
         include: "#expression-bare"
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 7a833786..4fa597d1 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -1375,7 +1375,7 @@ it's probably control flow like:
       <key>f-expression</key>
       <dict>
         <key>comment</key>
-        <string>All valid Python expressions, except comments and line cont</string>
+        <string>All valid Python expressions, except comments and line continuation</string>
         <key>patterns</key>
         <array>
           <dict>
diff --git a/grammars/src/comment.inc.syntax.yaml b/grammars/src/comment.inc.syntax.yaml
index 8555e562..d6a791f2 100644
--- a/grammars/src/comment.inc.syntax.yaml
+++ b/grammars/src/comment.inc.syntax.yaml
@@ -1,11 +1,10 @@
 ---
-repository:
-  comments${suffix}:
-    name: comment.line.number-sign.python
-    begin: (\#)
-    beginCaptures:
-      '1': {name: punctuation.definition.comment.python}
-    end: ($${marker})
-    patterns:
-      - include: '#codetags'
+comments${suffix}:
+  name: comment.line.number-sign.python
+  begin: (\#)
+  beginCaptures:
+    '1': {name: punctuation.definition.comment.python}
+  end: ($${marker})
+  patterns:
+    - include: '#codetags'
 ...
diff --git a/grammars/src/pyfstring.inc.syntax.yaml b/grammars/src/pyfstring.inc.syntax.yaml
index 4daed8b4..993707cf 100644
--- a/grammars/src/pyfstring.inc.syntax.yaml
+++ b/grammars/src/pyfstring.inc.syntax.yaml
@@ -1,177 +1,176 @@
 ---
-repository:
-  fstring-fnorm-quoted-${line}-line:
-    name: meta.fstring.python
-    begin: (\b[fF])([bBuU])?(${marker})
-    end: (\3)${guard}
-    beginCaptures:
-      # "storage.type.string.python" class should be the first one,
-      # because Atom, VSCode and GitHub don't understand scopes
-      # separated by whitespace, and simply use the first one
-      # of them.  Highlighting 'f' as 'storage.type' is more
-      # important for us than having other scopes.
-      '1': {name: storage.type.string.python
-                  string.quoted.${line}.python
-                  string.interpolated.python}
-      '2': {name: invalid.illegal.prefix.python}
-      '3': {name: string.quoted.${line}.python
-                  string.interpolated.python
-                  punctuation.definition.string.begin.python}
-    endCaptures:
-      '1': {name: string.quoted.${line}.python
-                  string.interpolated.python
-                  punctuation.definition.string.end.python}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#fstring-guts'
-      - include: '#fstring-illegal-${line}-brace'
-      - include: '#fstring-${line}-brace'
-      - include: '#fstring-${line}-core'
+fstring-fnorm-quoted-${line}-line:
+  name: meta.fstring.python
+  begin: (\b[fF])([bBuU])?(${marker})
+  end: (\3)${guard}
+  beginCaptures:
+    # "storage.type.string.python" class should be the first one,
+    # because Atom, VSCode and GitHub don't understand scopes
+    # separated by whitespace, and simply use the first one
+    # of them.  Highlighting 'f' as 'storage.type' is more
+    # important for us than having other scopes.
+    '1': {name: storage.type.string.python
+                string.quoted.${line}.python
+                string.interpolated.python}
+    '2': {name: invalid.illegal.prefix.python}
+    '3': {name: string.quoted.${line}.python
+                string.interpolated.python
+                punctuation.definition.string.begin.python}
+  endCaptures:
+    '1': {name: string.quoted.${line}.python
+                string.interpolated.python
+                punctuation.definition.string.end.python}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#fstring-guts'
+    - include: '#fstring-illegal-${line}-brace'
+    - include: '#fstring-${line}-brace'
+    - include: '#fstring-${line}-core'
 
-  fstring-normf-quoted-${line}-line:
-    name: meta.fstring.python
-    begin: (\b[bBuU])([fF])(${marker})
-    end: (\3)${guard}
-    beginCaptures:
-      '1': {name: invalid.illegal.prefix.python}
-      '2': {name: storage.type.string.python
-                  string.quoted.${line}.python
-                  string.interpolated.python}
-      '3': {name: string.quoted.${line}.python
-                  punctuation.definition.string.begin.python}
-    endCaptures:
-      '1': {name: string.quoted.${line}.python
-                  string.interpolated.python
-                  punctuation.definition.string.end.python}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#fstring-guts'
-      - include: '#fstring-illegal-${line}-brace'
-      - include: '#fstring-${line}-brace'
-      - include: '#fstring-${line}-core'
+fstring-normf-quoted-${line}-line:
+  name: meta.fstring.python
+  begin: (\b[bBuU])([fF])(${marker})
+  end: (\3)${guard}
+  beginCaptures:
+    '1': {name: invalid.illegal.prefix.python}
+    '2': {name: storage.type.string.python
+                string.quoted.${line}.python
+                string.interpolated.python}
+    '3': {name: string.quoted.${line}.python
+                punctuation.definition.string.begin.python}
+  endCaptures:
+    '1': {name: string.quoted.${line}.python
+                string.interpolated.python
+                punctuation.definition.string.end.python}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#fstring-guts'
+    - include: '#fstring-illegal-${line}-brace'
+    - include: '#fstring-${line}-brace'
+    - include: '#fstring-${line}-core'
 
-  fstring-raw-quoted-${line}-line:
-    name: meta.fstring.python
-    begin: (\b(?:[R][fF]|[fF][R]))(${marker})
-    end: (\2)${guard}
-    beginCaptures:
-      '1': {name: storage.type.string.python
-                  string.quoted.raw.${line}.python
-                  string.interpolated.python}
-      '2': {name: string.quoted.raw.${line}.python
-                  punctuation.definition.string.begin.python}
-    endCaptures:
-      '1': {name: string.quoted.raw.${line}.python
-                  string.interpolated.python
-                  punctuation.definition.string.end.python}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#fstring-raw-guts'
-      - include: '#fstring-illegal-${line}-brace'
-      - include: '#fstring-${line}-brace'
-      - include: '#fstring-raw-${line}-core'
+fstring-raw-quoted-${line}-line:
+  name: meta.fstring.python
+  begin: (\b(?:[R][fF]|[fF][R]))(${marker})
+  end: (\2)${guard}
+  beginCaptures:
+    '1': {name: storage.type.string.python
+                string.quoted.raw.${line}.python
+                string.interpolated.python}
+    '2': {name: string.quoted.raw.${line}.python
+                punctuation.definition.string.begin.python}
+  endCaptures:
+    '1': {name: string.quoted.raw.${line}.python
+                string.interpolated.python
+                punctuation.definition.string.end.python}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#fstring-raw-guts'
+    - include: '#fstring-illegal-${line}-brace'
+    - include: '#fstring-${line}-brace'
+    - include: '#fstring-raw-${line}-core'
 
-  fstring-${line}-core:
-    name: string.quoted.${line}.python string.interpolated.python
-    match: |
-      (?x)
-        (.+?)
-          (
-            (?# .* and .*? in multi-line match need special handling of
-              newlines otherwise SublimeText and Atom will match slightly
-              differently.
+fstring-${line}-core:
+  name: string.quoted.${line}.python string.interpolated.python
+  match: |
+    (?x)
+      (.+?)
+        (
+          (?# .* and .*? in multi-line match need special handling of
+            newlines otherwise SublimeText and Atom will match slightly
+            differently.
 
-              The guard for newlines has to be separate from the
-              lookahead because of special $ matching rule.)
-            ($\n?)
-            |
-            (?=[\\\}\{]|${marker}${guard})
-          )
-        (?# due to how multiline regexps are matched we need a special case
-          for matching a newline character)
-        | \n
+            The guard for newlines has to be separate from the
+            lookahead because of special $ matching rule.)
+          ($\n?)
+          |
+          (?=[\\\}\{]|${marker}${guard})
+        )
+      (?# due to how multiline regexps are matched we need a special case
+        for matching a newline character)
+      | \n
 
-  fstring-raw-${line}-core:
-    name: string.quoted.raw.${line}.python string.interpolated.python
-    match: |
-      (?x)
-        (.+?)
-          (
-            (?# .* and .*? in multi-line match need special handling of
-              newlines otherwise SublimeText and Atom will match slightly
-              differently.
+fstring-raw-${line}-core:
+  name: string.quoted.raw.${line}.python string.interpolated.python
+  match: |
+    (?x)
+      (.+?)
+        (
+          (?# .* and .*? in multi-line match need special handling of
+            newlines otherwise SublimeText and Atom will match slightly
+            differently.
 
-              The guard for newlines has to be separate from the
-              lookahead because of special $ matching rule.)
-            ($\n?)
-            |
-            (?=[\\\}\{]|${marker}${guard})
-          )
-        (?# due to how multiline regexps are matched we need a special case
-          for matching a newline character)
-        | \n
+            The guard for newlines has to be separate from the
+            lookahead because of special $ matching rule.)
+          ($\n?)
+          |
+          (?=[\\\}\{]|${marker}${guard})
+        )
+      (?# due to how multiline regexps are matched we need a special case
+        for matching a newline character)
+      | \n
 
-  fstring-${line}-brace:
-    comment: value interpolation using { ... }
-    begin: (\{)
-    end: |
-      (?x)
-        (\})${fguard}
-    beginCaptures:
-      '1': {name: constant.character.format.placeholder.other.python}
-    endCaptures:
-      '1': {name: constant.character.format.placeholder.other.python}
-    patterns:
-      - include: '#fstring-terminator-${line}'
-      - include: '#f-expression'
+fstring-${line}-brace:
+  comment: value interpolation using { ... }
+  begin: (\{)
+  end: |
+    (?x)
+      (\})${fguard}
+  beginCaptures:
+    '1': {name: constant.character.format.placeholder.other.python}
+  endCaptures:
+    '1': {name: constant.character.format.placeholder.other.python}
+  patterns:
+    - include: '#fstring-terminator-${line}'
+    - include: '#f-expression'
 
-  fstring-terminator-${line}:
-    patterns:
-      - name: storage.type.format.python
-        match: (![rsa])(?=})
-      - match: |
-          (?x)
-            (![rsa])?
-              ( : \w? [<>=^]? [-+ ]? \#?
-                \d* ,? (\.\d+)? [bcdeEfFgGnosxX%]? )(?=})
-        captures:
-          # We use this awkward scope name instead of perhaps more
-          # elegant "support.other.format.python" because it appears
-          # that by default it gives a better visual result in various
-          # systems (e.g. GitHub). This is due to the fact that
-          # "storage.type..." is more likely to have special
-          # highlighting in any given color scheme than
-          # "support.other..."
-          #
-          '1': {name: storage.type.format.python}
-          '2': {name: storage.type.format.python}
+fstring-terminator-${line}:
+  patterns:
+    - name: storage.type.format.python
+      match: (![rsa])(?=})
+    - match: |
+        (?x)
+          (![rsa])?
+            ( : \w? [<>=^]? [-+ ]? \#?
+              \d* ,? (\.\d+)? [bcdeEfFgGnosxX%]? )(?=})
+      captures:
+        # We use this awkward scope name instead of perhaps more
+        # elegant "support.other.format.python" because it appears
+        # that by default it gives a better visual result in various
+        # systems (e.g. GitHub). This is due to the fact that
+        # "storage.type..." is more likely to have special
+        # highlighting in any given color scheme than
+        # "support.other..."
+        #
+        '1': {name: storage.type.format.python}
+        '2': {name: storage.type.format.python}
 
-      - include: '#fstring-terminator-${line}-tail'
+    - include: '#fstring-terminator-${line}-tail'
 
-  fstring-terminator-${line}-tail:
-    begin: (![rsa])?(:)(?=.*?{)
-    end: (?=})${fguard}
-    beginCaptures:
-      '1': {name: storage.type.format.python}
-      '2': {name: storage.type.format.python}
+fstring-terminator-${line}-tail:
+  begin: (![rsa])?(:)(?=.*?{)
+  end: (?=})${fguard}
+  beginCaptures:
+    '1': {name: storage.type.format.python}
+    '2': {name: storage.type.format.python}
 
-    patterns:
-      - include: '#fstring-illegal-${line}-brace'
-      - include: '#fstring-${line}-brace'
-      - name: storage.type.format.python
-        match: ([bcdeEfFgGnosxX%])(?=})
-      - name: storage.type.format.python
-        match: (\.\d+)
-      - name: storage.type.format.python
-        match: (,)
-      - name: storage.type.format.python
-        match: (\d+)
-      - name: storage.type.format.python
-        match: (\#)
-      - name: storage.type.format.python
-        match: ([-+ ])
-      - name: storage.type.format.python
-        match: ([<>=^])
-      - name: storage.type.format.python
-        match: (\w)
+  patterns:
+    - include: '#fstring-illegal-${line}-brace'
+    - include: '#fstring-${line}-brace'
+    - name: storage.type.format.python
+      match: ([bcdeEfFgGnosxX%])(?=})
+    - name: storage.type.format.python
+      match: (\.\d+)
+    - name: storage.type.format.python
+      match: (,)
+    - name: storage.type.format.python
+      match: (\d+)
+    - name: storage.type.format.python
+      match: (\#)
+    - name: storage.type.format.python
+      match: ([-+ ])
+    - name: storage.type.format.python
+      match: ([<>=^])
+    - name: storage.type.format.python
+      match: (\w)
 ...
diff --git a/grammars/src/pystring.inc.syntax.yaml b/grammars/src/pystring.inc.syntax.yaml
index 8bd53282..5127ae72 100644
--- a/grammars/src/pystring.inc.syntax.yaml
+++ b/grammars/src/pystring.inc.syntax.yaml
@@ -1,118 +1,117 @@
 ---
-repository:
-  string-raw-quoted-${line}-line:
-    name: string.quoted.raw.${line}.python
-    begin: \b(([uU]R)|(R))(${marker})
-    end: (\4)${guard}
-    beginCaptures:
-      '2': {name: invalid.deprecated.prefix.python}
-      '3': {name: storage.type.string.python}
-      '4': {name: punctuation.definition.string.begin.python}
-    endCaptures:
-      '1': {name: punctuation.definition.string.end.python}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#string-${line}-bad-brace1-formatting-raw'
-      - include: '#string-${line}-bad-brace2-formatting-raw'
-      - include: '#string-raw-guts'
+string-raw-quoted-${line}-line:
+  name: string.quoted.raw.${line}.python
+  begin: \b(([uU]R)|(R))(${marker})
+  end: (\4)${guard}
+  beginCaptures:
+    '2': {name: invalid.deprecated.prefix.python}
+    '3': {name: storage.type.string.python}
+    '4': {name: punctuation.definition.string.begin.python}
+  endCaptures:
+    '1': {name: punctuation.definition.string.end.python}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#string-${line}-bad-brace1-formatting-raw'
+    - include: '#string-${line}-bad-brace2-formatting-raw'
+    - include: '#string-raw-guts'
 
-  string-bin-quoted-${line}-line:
-    name: string.quoted.binary.${line}.python
-    begin: (\b[bB])(${marker})
-    end: (\2)${guard}
-    beginCaptures:
-      '1': {name: storage.type.string.python}
-      '2': {name: punctuation.definition.string.begin.python}
-    endCaptures:
-      '1': {name: punctuation.definition.string.end.python}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#string-entity'
+string-bin-quoted-${line}-line:
+  name: string.quoted.binary.${line}.python
+  begin: (\b[bB])(${marker})
+  end: (\2)${guard}
+  beginCaptures:
+    '1': {name: storage.type.string.python}
+    '2': {name: punctuation.definition.string.begin.python}
+  endCaptures:
+    '1': {name: punctuation.definition.string.end.python}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#string-entity'
 
-  string-raw-bin-quoted-${line}-line:
-    name: string.quoted.raw.binary.${line}.python
-    begin: (\b(?:R[bB]|[bB]R))(${marker})
-    end: (\2)${guard}
-    beginCaptures:
-      '1': {name: storage.type.string.python}
-      '2': {name: punctuation.definition.string.begin.python}
-    endCaptures:
-      '1': {name: punctuation.definition.string.end.python}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#string-raw-bin-guts'
+string-raw-bin-quoted-${line}-line:
+  name: string.quoted.raw.binary.${line}.python
+  begin: (\b(?:R[bB]|[bB]R))(${marker})
+  end: (\2)${guard}
+  beginCaptures:
+    '1': {name: storage.type.string.python}
+    '2': {name: punctuation.definition.string.begin.python}
+  endCaptures:
+    '1': {name: punctuation.definition.string.end.python}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#string-raw-bin-guts'
 
-  string-quoted-${line}-line:
-    name: string.quoted.${line}.python
-    begin: (?:\b([rR])(?=[uU]))?([uU])?(${marker})
-    end: (\3)${guard}
-    beginCaptures:
-      '1': {name: invalid.illegal.prefix.python}
-      '2': {name: storage.type.string.python}
-      '3': {name: punctuation.definition.string.begin.python}
-    endCaptures:
-      '1': {name: punctuation.definition.string.end.python}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#string-${line}-bad-brace1-formatting-unicode'
-      - include: '#string-${line}-bad-brace2-formatting-unicode'
-      - include: '#string-unicode-guts'
+string-quoted-${line}-line:
+  name: string.quoted.${line}.python
+  begin: (?:\b([rR])(?=[uU]))?([uU])?(${marker})
+  end: (\3)${guard}
+  beginCaptures:
+    '1': {name: invalid.illegal.prefix.python}
+    '2': {name: storage.type.string.python}
+    '3': {name: punctuation.definition.string.begin.python}
+  endCaptures:
+    '1': {name: punctuation.definition.string.end.python}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#string-${line}-bad-brace1-formatting-unicode'
+    - include: '#string-${line}-bad-brace2-formatting-unicode'
+    - include: '#string-unicode-guts'
 
-  string-${line}-bad-brace1-formatting-unicode:
-    comment: template using {% ... %}
-    begin: |
-      (?x)
-          (?= \{%
-                ( .*? (?!${marker}${guard}) )
-              %\}
-          )
-    end: (?=${marker}${guard})
-    patterns:
-      - include: '#escape-sequence-unicode'
-      - include: '#escape-sequence'
-      - include: '#string-line-continuation'
+string-${line}-bad-brace1-formatting-unicode:
+  comment: template using {% ... %}
+  begin: |
+    (?x)
+        (?= \{%
+              ( .*? (?!${marker}${guard}) )
+            %\}
+        )
+  end: (?=${marker}${guard})
+  patterns:
+    - include: '#escape-sequence-unicode'
+    - include: '#escape-sequence'
+    - include: '#string-line-continuation'
 
-  string-${line}-bad-brace1-formatting-raw:
-    comment: template using {% ... %}
-    begin: |
-      (?x)
-          (?= \{%
-                ( .*? (?!${marker}${guard}) )
-              %\}
-          )
-    end: (?=${marker}${guard})
-    patterns:
-      - include: '#string-consume-escape'
+string-${line}-bad-brace1-formatting-raw:
+  comment: template using {% ... %}
+  begin: |
+    (?x)
+        (?= \{%
+              ( .*? (?!${marker}${guard}) )
+            %\}
+        )
+  end: (?=${marker}${guard})
+  patterns:
+    - include: '#string-consume-escape'
 
-  string-${line}-bad-brace2-formatting-unicode:
-    comment: odd format or format-like syntax
-    begin: |
-      (?x)
-          (?!\{\{)
-          (?= \{ (
-                    \w*? (?!${marker}${guard}) [^!:\.\[}\w]
-                 )
-              .*?(?!${marker}${guard})
-              \}
-          )
-    end: (?=${marker}${guard})
-    patterns:
-      - include: '#escape-sequence-unicode'
-      - include: '#string-entity'
+string-${line}-bad-brace2-formatting-unicode:
+  comment: odd format or format-like syntax
+  begin: |
+    (?x)
+        (?!\{\{)
+        (?= \{ (
+                  \w*? (?!${marker}${guard}) [^!:\.\[}\w]
+               )
+            .*?(?!${marker}${guard})
+            \}
+        )
+  end: (?=${marker}${guard})
+  patterns:
+    - include: '#escape-sequence-unicode'
+    - include: '#string-entity'
 
-  string-${line}-bad-brace2-formatting-raw:
-    comment: odd format or format-like syntax
-    begin: |
-      (?x)
-          (?!\{\{)
-          (?= \{ (
-                    \w*? (?!${marker}${guard}) [^!:\.\[}\w]
-                 )
-              .*?(?!${marker}${guard})
-              \}
-          )
-    end: (?=${marker}${guard})
-    patterns:
-      - include: '#string-consume-escape'
-      - include: '#string-formatting'
+string-${line}-bad-brace2-formatting-raw:
+  comment: odd format or format-like syntax
+  begin: |
+    (?x)
+        (?!\{\{)
+        (?= \{ (
+                  \w*? (?!${marker}${guard}) [^!:\.\[}\w]
+               )
+            .*?(?!${marker}${guard})
+            \}
+        )
+  end: (?=${marker}${guard})
+  patterns:
+    - include: '#string-consume-escape'
+    - include: '#string-formatting'
 ...
diff --git a/grammars/src/regexp-common.inc.syntax.yaml b/grammars/src/regexp-common.inc.syntax.yaml
index e367af87..828a630b 100644
--- a/grammars/src/regexp-common.inc.syntax.yaml
+++ b/grammars/src/regexp-common.inc.syntax.yaml
@@ -1,128 +1,127 @@
 ---
-repository:
-  regexp-base-expression:
-    patterns:
-      - include: '#regexp-quantifier'
-      - include: '#regexp-base-common'
+regexp-base-expression:
+  patterns:
+    - include: '#regexp-quantifier'
+    - include: '#regexp-base-common'
 
-  fregexp-base-expression:
-    patterns:
-      - include: '#fregexp-quantifier'
-      - include: '#fstring-formatting-braces'
-      - match: \{.*?\}
-      - include: '#regexp-base-common'
+fregexp-base-expression:
+  patterns:
+    - include: '#fregexp-quantifier'
+    - include: '#fstring-formatting-braces'
+    - match: \{.*?\}
+    - include: '#regexp-base-common'
 
-  fstring-formatting-braces:
-    patterns:
-      - comment: empty braces are illegal
-        match: ({)(\s*?)(})
-        captures:
-          '1': {name: constant.character.format.placeholder.other.python}
-          '2': {name: invalid.illegal.brace.python}
-          '3': {name: constant.character.format.placeholder.other.python}
-      - name: constant.character.escape.python
-        match: ({{|}})
+fstring-formatting-braces:
+  patterns:
+    - comment: empty braces are illegal
+      match: ({)(\s*?)(})
+      captures:
+        '1': {name: constant.character.format.placeholder.other.python}
+        '2': {name: invalid.illegal.brace.python}
+        '3': {name: constant.character.format.placeholder.other.python}
+    - name: constant.character.escape.python
+      match: ({{|}})
 
-  regexp-base-common:
-    patterns:
-      - name: support.other.match.any.regexp
-        match: \.
-      - name: support.other.match.begin.regexp
-        match: \^
-      - name: support.other.match.end.regexp
-        match: \$
-      - name: keyword.operator.quantifier.regexp
-        match: '[+*?]\??'
-      - name: keyword.operator.disjunction.regexp
-        match: \|
-      - include: '#regexp-escape-sequence'
+regexp-base-common:
+  patterns:
+    - name: support.other.match.any.regexp
+      match: \.
+    - name: support.other.match.begin.regexp
+      match: \^
+    - name: support.other.match.end.regexp
+      match: \$
+    - name: keyword.operator.quantifier.regexp
+      match: '[+*?]\??'
+    - name: keyword.operator.disjunction.regexp
+      match: \|
+    - include: '#regexp-escape-sequence'
 
-  regexp-quantifier:
-    name: keyword.operator.quantifier.regexp
-    match: |
-      (?x)
-        \{(
-          \d+ | \d+,(\d+)? | ,\d+
-        )\}
+regexp-quantifier:
+  name: keyword.operator.quantifier.regexp
+  match: |
+    (?x)
+      \{(
+        \d+ | \d+,(\d+)? | ,\d+
+      )\}
 
-  fregexp-quantifier:
-    name: keyword.operator.quantifier.regexp
-    match: |
-      (?x)
-        \{\{(
-          \d+ | \d+,(\d+)? | ,\d+
-        )\}\}
+fregexp-quantifier:
+  name: keyword.operator.quantifier.regexp
+  match: |
+    (?x)
+      \{\{(
+        \d+ | \d+,(\d+)? | ,\d+
+      )\}\}
 
-  regexp-backreference-number:
-    name: meta.backreference.regexp
-    match: (\\[1-9]\d?)
-    captures:
-      '1': {name: entity.name.tag.backreference.regexp}
+regexp-backreference-number:
+  name: meta.backreference.regexp
+  match: (\\[1-9]\d?)
+  captures:
+    '1': {name: entity.name.tag.backreference.regexp}
 
-  regexp-backreference:
-    name: meta.backreference.named.regexp
-    match: |
-      (?x)
-        (\()  (\?P= \w+(?:\s+[[:alnum:]]+)?)  (\))
-    captures:
-      '1': {name: punctuation.parenthesis.backreference.named.begin.regexp
-                  support.other.parenthesis.regexp}
-      '2': {name: entity.name.tag.named.backreference.regexp}
-      '3': {name: punctuation.parenthesis.backreference.named.end.regexp
-                  support.other.parenthesis.regexp}
+regexp-backreference:
+  name: meta.backreference.named.regexp
+  match: |
+    (?x)
+      (\()  (\?P= \w+(?:\s+[[:alnum:]]+)?)  (\))
+  captures:
+    '1': {name: punctuation.parenthesis.backreference.named.begin.regexp
+                support.other.parenthesis.regexp}
+    '2': {name: entity.name.tag.named.backreference.regexp}
+    '3': {name: punctuation.parenthesis.backreference.named.end.regexp
+                support.other.parenthesis.regexp}
 
-  regexp-flags:
-    name: storage.modifier.flag.regexp
-    match: \(\?[aiLmsux]+\)
+regexp-flags:
+  name: storage.modifier.flag.regexp
+  match: \(\?[aiLmsux]+\)
 
-  regexp-escape-special:
-    name: support.other.escape.special.regexp
-    match: \\([AbBdDsSwWZ])
+regexp-escape-special:
+  name: support.other.escape.special.regexp
+  match: \\([AbBdDsSwWZ])
 
-  regexp-escape-character:
-    name: constant.character.escape.regexp
-    match: |
-      (?x)
-        \\ (
-              x[0-9A-Fa-f]{2}
-              | 0[0-7]{1,2}
-              | [0-7]{3}
-           )
+regexp-escape-character:
+  name: constant.character.escape.regexp
+  match: |
+    (?x)
+      \\ (
+            x[0-9A-Fa-f]{2}
+            | 0[0-7]{1,2}
+            | [0-7]{3}
+         )
 
-  regexp-escape-unicode:
-    name: constant.character.unicode.regexp
-    match: |
-      (?x)
-        \\ (
-              u[0-9A-Fa-f]{4}
-              | U[0-9A-Fa-f]{8}
-           )
+regexp-escape-unicode:
+  name: constant.character.unicode.regexp
+  match: |
+    (?x)
+      \\ (
+            u[0-9A-Fa-f]{4}
+            | U[0-9A-Fa-f]{8}
+         )
 
-  regexp-escape-catchall:
-    name: constant.character.escape.regexp
-    match: \\(.|\n)
+regexp-escape-catchall:
+  name: constant.character.escape.regexp
+  match: \\(.|\n)
 
-  regexp-escape-sequence:
-    patterns:
-      - include: '#regexp-escape-special'
-      - include: '#regexp-escape-character'
-      - include: '#regexp-escape-unicode'
-      - include: '#regexp-backreference-number'
-      - include: '#regexp-escape-catchall'
+regexp-escape-sequence:
+  patterns:
+    - include: '#regexp-escape-special'
+    - include: '#regexp-escape-character'
+    - include: '#regexp-escape-unicode'
+    - include: '#regexp-backreference-number'
+    - include: '#regexp-escape-catchall'
 
-  regexp-charecter-set-escapes:
-    patterns:
-      - name: constant.character.escape.regexp
-        match: \\[abfnrtv\\]
-      - include: '#regexp-escape-special'
-      - name: constant.character.escape.regexp
-        match: \\([0-7]{1,3})
-      - include: '#regexp-escape-character'
-      - include: '#regexp-escape-unicode'
-      - include: '#regexp-escape-catchall'
+regexp-charecter-set-escapes:
+  patterns:
+    - name: constant.character.escape.regexp
+      match: \\[abfnrtv\\]
+    - include: '#regexp-escape-special'
+    - name: constant.character.escape.regexp
+      match: \\([0-7]{1,3})
+    - include: '#regexp-escape-character'
+    - include: '#regexp-escape-unicode'
+    - include: '#regexp-escape-catchall'
 
-  codetags:
-    match: (?:\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\b)
-    captures:
-      '1': {name: keyword.codetag.notation.python}
+codetags:
+  match: (?:\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\b)
+  captures:
+    '1': {name: keyword.codetag.notation.python}
 ...
diff --git a/grammars/src/regexp.inc.syntax.yaml b/grammars/src/regexp.inc.syntax.yaml
index ea55ff55..aac9e286 100644
--- a/grammars/src/regexp.inc.syntax.yaml
+++ b/grammars/src/regexp.inc.syntax.yaml
@@ -1,170 +1,169 @@
 ---
-repository:
-  ${prefix}${basename}-expression:
-    patterns:
-      - include: '#${basename}-base-expression'
-      - include: '#${prefix}regexp-character-set'
-      - include: '#${prefix}regexp-comments'
-      - include: '#regexp-flags'
-      - include: '#${prefix}regexp-named-group'
-      - include: '#regexp-backreference'
-      - include: '#${prefix}${basename}-lookahead'
-      - include: '#${prefix}${basename}-lookahead-negative'
-      - include: '#${prefix}${basename}-lookbehind'
-      - include: '#${prefix}${basename}-lookbehind-negative'
-      - include: '#${prefix}${basename}-conditional'
-      - include: '#${prefix}${basename}-parentheses-non-capturing'
-      - include: '#${prefix}${basename}-parentheses'
-      ${nested}
+${prefix}${basename}-expression:
+  patterns:
+    - include: '#${basename}-base-expression'
+    - include: '#${prefix}regexp-character-set'
+    - include: '#${prefix}regexp-comments'
+    - include: '#regexp-flags'
+    - include: '#${prefix}regexp-named-group'
+    - include: '#regexp-backreference'
+    - include: '#${prefix}${basename}-lookahead'
+    - include: '#${prefix}${basename}-lookahead-negative'
+    - include: '#${prefix}${basename}-lookbehind'
+    - include: '#${prefix}${basename}-lookbehind-negative'
+    - include: '#${prefix}${basename}-conditional'
+    - include: '#${prefix}${basename}-parentheses-non-capturing'
+    - include: '#${prefix}${basename}-parentheses'
+    ${nested}
 
-  ${prefix}regexp-character-set:
-    patterns:
-      - match: |
-          (?x)
-            \[ \^? \] (?! .*?\])
-      - name: meta.character.set.regexp
-        begin: (\[)(\^)?(\])?
-        end: (\]${marker})${guard}
-        beginCaptures:
-          '1': {name: constant.other.set.regexp
-                      punctuation.character.set.begin.regexp}
-          '2': {name: keyword.operator.negation.regexp}
-          '3': {name: constant.character.set.regexp}
-        endCaptures:
-          '1': {name: constant.other.set.regexp
-                      punctuation.character.set.end.regexp}
-          '2': {name: invalid.illegal.newline.python}
-        patterns:
-          - include: '#regexp-charecter-set-escapes'
-          - name: constant.character.set.regexp
-            match: '[^\n]'
+${prefix}regexp-character-set:
+  patterns:
+    - match: |
+        (?x)
+          \[ \^? \] (?! .*?\])
+    - name: meta.character.set.regexp
+      begin: (\[)(\^)?(\])?
+      end: (\]${marker})${guard}
+      beginCaptures:
+        '1': {name: constant.other.set.regexp
+                    punctuation.character.set.begin.regexp}
+        '2': {name: keyword.operator.negation.regexp}
+        '3': {name: constant.character.set.regexp}
+      endCaptures:
+        '1': {name: constant.other.set.regexp
+                    punctuation.character.set.end.regexp}
+        '2': {name: invalid.illegal.newline.python}
+      patterns:
+        - include: '#regexp-charecter-set-escapes'
+        - name: constant.character.set.regexp
+          match: '[^\n]'
 
-  ${prefix}${basename}-named-group:
-    name: meta.named.regexp
-    begin: |
-      (?x)
-        (\()  (\?P <\w+(?:\s+[[:alnum:]]+)?>)
-    end: (\)${marker})${guard}
-    beginCaptures:
-      '1': {name: punctuation.parenthesis.named.begin.regexp
-                  support.other.parenthesis.regexp}
-      '2': {name: entity.name.tag.named.group.regexp}
-    endCaptures:
-      '1': {name: punctuation.parenthesis.named.end.regexp
-                  support.other.parenthesis.regexp}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#${prefix}${basename}-expression'
-      ${nested}
+${prefix}${basename}-named-group:
+  name: meta.named.regexp
+  begin: |
+    (?x)
+      (\()  (\?P <\w+(?:\s+[[:alnum:]]+)?>)
+  end: (\)${marker})${guard}
+  beginCaptures:
+    '1': {name: punctuation.parenthesis.named.begin.regexp
+                support.other.parenthesis.regexp}
+    '2': {name: entity.name.tag.named.group.regexp}
+  endCaptures:
+    '1': {name: punctuation.parenthesis.named.end.regexp
+                support.other.parenthesis.regexp}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#${prefix}${basename}-expression'
+    ${nested}
 
-  ${prefix}regexp-comments:
-    name: comment.regexp
-    begin: \(\?#
-    end: (\)${marker})${guard}
-    beginCaptures:
-      '0': {name: punctuation.comment.begin.regexp}
-    endCaptures:
-      '1': {name: punctuation.comment.end.regexp}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#codetags'
+${prefix}regexp-comments:
+  name: comment.regexp
+  begin: \(\?#
+  end: (\)${marker})${guard}
+  beginCaptures:
+    '0': {name: punctuation.comment.begin.regexp}
+  endCaptures:
+    '1': {name: punctuation.comment.end.regexp}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#codetags'
 
-  ${prefix}${basename}-lookahead:
-    begin: '(\()\?='
-    end: (\)${marker})${guard}
-    beginCaptures:
-      '0': {name: keyword.operator.lookahead.regexp}
-      '1': {name: punctuation.parenthesis.lookahead.begin.regexp}
-    endCaptures:
-      '1': {name: punctuation.parenthesis.lookahead.end.regexp
-                  keyword.operator.lookahead.regexp}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#${prefix}${basename}-expression'
-      ${nested}
+${prefix}${basename}-lookahead:
+  begin: '(\()\?='
+  end: (\)${marker})${guard}
+  beginCaptures:
+    '0': {name: keyword.operator.lookahead.regexp}
+    '1': {name: punctuation.parenthesis.lookahead.begin.regexp}
+  endCaptures:
+    '1': {name: punctuation.parenthesis.lookahead.end.regexp
+                keyword.operator.lookahead.regexp}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#${prefix}${basename}-expression'
+    ${nested}
 
-  ${prefix}${basename}-lookahead-negative:
-    begin: '(\()\?!'
-    end: (\)${marker})${guard}
-    beginCaptures:
-      '0': {name: keyword.operator.lookahead.negative.regexp}
-      '1': {name: punctuation.parenthesis.lookahead.begin.regexp}
-    endCaptures:
-      '1': {name: punctuation.parenthesis.lookahead.end.regexp
-                  keyword.operator.lookahead.negative.regexp}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#${prefix}${basename}-expression'
-      ${nested}
+${prefix}${basename}-lookahead-negative:
+  begin: '(\()\?!'
+  end: (\)${marker})${guard}
+  beginCaptures:
+    '0': {name: keyword.operator.lookahead.negative.regexp}
+    '1': {name: punctuation.parenthesis.lookahead.begin.regexp}
+  endCaptures:
+    '1': {name: punctuation.parenthesis.lookahead.end.regexp
+                keyword.operator.lookahead.negative.regexp}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#${prefix}${basename}-expression'
+    ${nested}
 
-  ${prefix}${basename}-lookbehind:
-    begin: '(\()\?<='
-    end: (\)${marker})${guard}
-    beginCaptures:
-      '0': {name: keyword.operator.lookbehind.regexp}
-      '1': {name: punctuation.parenthesis.lookbehind.begin.regexp}
-    endCaptures:
-      '1': {name: punctuation.parenthesis.lookbehind.end.regexp
-                  keyword.operator.lookbehind.regexp}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#${prefix}${basename}-expression'
-      ${nested}
+${prefix}${basename}-lookbehind:
+  begin: '(\()\?<='
+  end: (\)${marker})${guard}
+  beginCaptures:
+    '0': {name: keyword.operator.lookbehind.regexp}
+    '1': {name: punctuation.parenthesis.lookbehind.begin.regexp}
+  endCaptures:
+    '1': {name: punctuation.parenthesis.lookbehind.end.regexp
+                keyword.operator.lookbehind.regexp}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#${prefix}${basename}-expression'
+    ${nested}
 
-  ${prefix}${basename}-lookbehind-negative:
-    begin: '(\()\?<!'
-    end: (\)${marker})${guard}
-    beginCaptures:
-      '0': {name: keyword.operator.lookbehind.negative.regexp}
-      '1': {name: punctuation.parenthesis.lookbehind.begin.regexp}
-    endCaptures:
-      '1': {name: punctuation.parenthesis.lookbehind.end.regexp
-                  keyword.operator.lookbehind.negative.regexp}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#${prefix}${basename}-expression'
-      ${nested}
+${prefix}${basename}-lookbehind-negative:
+  begin: '(\()\?<!'
+  end: (\)${marker})${guard}
+  beginCaptures:
+    '0': {name: keyword.operator.lookbehind.negative.regexp}
+    '1': {name: punctuation.parenthesis.lookbehind.begin.regexp}
+  endCaptures:
+    '1': {name: punctuation.parenthesis.lookbehind.end.regexp
+                keyword.operator.lookbehind.negative.regexp}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#${prefix}${basename}-expression'
+    ${nested}
 
-  ${prefix}${basename}-conditional:
-    begin: '(\()\?\((\w+(?:\s+[[:alnum:]]+)?|\d+)\)'
-    end: (\)${marker})${guard}
-    beginCaptures:
-      '0': {name: keyword.operator.conditional.regexp}
-      '1': {name: punctuation.parenthesis.conditional.begin.regexp}
-    endCaptures:
-      '1': {name: punctuation.parenthesis.conditional.end.regexp
-                  keyword.operator.conditional.negative.regexp}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#${prefix}${basename}-expression'
-      ${nested}
+${prefix}${basename}-conditional:
+  begin: '(\()\?\((\w+(?:\s+[[:alnum:]]+)?|\d+)\)'
+  end: (\)${marker})${guard}
+  beginCaptures:
+    '0': {name: keyword.operator.conditional.regexp}
+    '1': {name: punctuation.parenthesis.conditional.begin.regexp}
+  endCaptures:
+    '1': {name: punctuation.parenthesis.conditional.end.regexp
+                keyword.operator.conditional.negative.regexp}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#${prefix}${basename}-expression'
+    ${nested}
 
-  ${prefix}${basename}-parentheses-non-capturing:
-    begin: '\(\?:'
-    end: (\)${marker})${guard}
-    beginCaptures:
-      '0': {name: punctuation.parenthesis.non-capturing.begin.regexp
-                  support.other.parenthesis.regexp}
-    endCaptures:
-      '1': {name: punctuation.parenthesis.non-capturing.end.regexp
-                  support.other.parenthesis.regexp}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#${prefix}${basename}-expression'
-      ${nested}
+${prefix}${basename}-parentheses-non-capturing:
+  begin: '\(\?:'
+  end: (\)${marker})${guard}
+  beginCaptures:
+    '0': {name: punctuation.parenthesis.non-capturing.begin.regexp
+                support.other.parenthesis.regexp}
+  endCaptures:
+    '1': {name: punctuation.parenthesis.non-capturing.end.regexp
+                support.other.parenthesis.regexp}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#${prefix}${basename}-expression'
+    ${nested}
 
-  ${prefix}${basename}-parentheses:
-    begin: \(
-    end: (\)${marker})${guard}
-    beginCaptures:
-      '0': {name: punctuation.parenthesis.begin.regexp
-                  support.other.parenthesis.regexp}
-    endCaptures:
-      '1': {name: punctuation.parenthesis.end.regexp
-                  support.other.parenthesis.regexp}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#${prefix}${basename}-expression'
-      ${nested}
+${prefix}${basename}-parentheses:
+  begin: \(
+  end: (\)${marker})${guard}
+  beginCaptures:
+    '0': {name: punctuation.parenthesis.begin.regexp
+                support.other.parenthesis.regexp}
+  endCaptures:
+    '1': {name: punctuation.parenthesis.end.regexp
+                support.other.parenthesis.regexp}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#${prefix}${basename}-expression'
+    ${nested}
 
 ...
diff --git a/grammars/src/regexp.wrapper.syntax.yaml b/grammars/src/regexp.wrapper.syntax.yaml
index d18a2212..58ca0f30 100644
--- a/grammars/src/regexp.wrapper.syntax.yaml
+++ b/grammars/src/regexp.wrapper.syntax.yaml
@@ -1,17 +1,16 @@
 ---
-repository:
-  ${basename}-${prefix}line:
-    name: ${scopename}
-    begin: \b(([uU]r)|(${modifier}r)|(r${modifier}?))${bquote}
-    end: ${equote}
-    beginCaptures:
-      '2': {name: invalid.deprecated.prefix.python}
-      '3': {name: storage.type.string.python}
-      '4': {name: storage.type.string.python}
-      '5': {name: punctuation.definition.string.begin.python}
-    endCaptures:
-      '1': {name: punctuation.definition.string.end.python}
-      '2': {name: invalid.illegal.newline.python}
-    patterns:
-      - include: '#${prefix}${basename}-expression'
+${basename}-${prefix}line:
+  name: ${scopename}
+  begin: \b(([uU]r)|(${modifier}r)|(r${modifier}?))${bquote}
+  end: ${equote}
+  beginCaptures:
+    '2': {name: invalid.deprecated.prefix.python}
+    '3': {name: storage.type.string.python}
+    '4': {name: storage.type.string.python}
+    '5': {name: punctuation.definition.string.begin.python}
+  endCaptures:
+    '1': {name: punctuation.definition.string.end.python}
+    '2': {name: invalid.illegal.newline.python}
+  patterns:
+    - include: '#${prefix}${basename}-expression'
 ...
diff --git a/package.json b/package.json
index f872035a..92b1a2ec 100644
--- a/package.json
+++ b/package.json
@@ -69,6 +69,7 @@
   },
   "devDependencies": {
     "oniguruma": "^7.0.0",
-    "syntaxdev": "0.0.16"
-  }
+    "syntaxdev": "^0.1.0"
+  },
+  "dependencies": {}
 }

From e57ccc12702adb2232c36e0564f3fea7c56a82a9 Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@magic.io>
Date: Fri, 15 Mar 2019 00:39:40 -0400
Subject: [PATCH 50/65] Fix the 'make devenv' target

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index f690dbd9..85c19a17 100644
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,7 @@ test: ci-test
 	atom -t test/atom-spec
 
 devenv:
-	npm install syntaxdev@0.0.16
+	npm install --dev
 
 release:
 	./node_modules/.bin/syntaxdev build-plist --in grammars/src/MagicPython.syntax.yaml --out grammars/MagicPython.tmLanguage

From c0f8d514bbe6e9d3899f2b002bcd6971aef5e34b Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@edgedb.com>
Date: Thu, 17 Oct 2019 17:03:25 -0400
Subject: [PATCH 51/65] Add a `meta.member.access.python` scope.

Add a `meta.member.access.python` scope wrapping around any attribute
access or method call.

Fixes #188.
---
 grammars/MagicPython.cson            |    2 +
 grammars/MagicPython.tmLanguage      |    4 +
 grammars/src/MagicPython.syntax.yaml |    2 +
 misc/scopes                          |    1 +
 test/atom-spec/python-spec.js        | 1036 +++++++++++++-------------
 test/builtins/builtins3.py           |  156 ++--
 test/builtins/builtins4.py           |   25 +-
 test/builtins/builtins5.py           |   27 +-
 test/calls/call3.py                  |   23 +-
 test/calls/call4.py                  |   17 +-
 test/calls/call7.py                  |   65 +-
 test/calls/call8.py                  |   69 +-
 test/calls/print1.py                 |    9 +-
 test/classes/class11.py              |   21 +-
 test/classes/class12.py              |   21 +-
 test/classes/class14.py              |   13 +-
 test/classes/class2.py               |    9 +-
 test/classes/super1.py               |   64 +-
 test/expressions/const1.py           |   21 +-
 test/expressions/expr10.py           |    5 +-
 test/expressions/expr11.py           |   15 +-
 test/expressions/expr15.py           |    5 +-
 test/expressions/expr18.py           |    9 +-
 test/expressions/expr19.py           |   39 +-
 test/expressions/expr7.py            |   13 +-
 test/fstrings/comment4.py            |   66 +-
 test/fstrings/simple2.py             |    5 +-
 test/illegals/illegal1.py            |   15 +-
 test/regexp/python8.py               |  321 ++++----
 test/statements/import5.py           |    5 +-
 test/strings/bug2.py                 |    6 +-
 test/strings/format2.py              |   15 +-
 32 files changed, 1068 insertions(+), 1036 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 8fe447f9..33f23dad 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -407,6 +407,7 @@ repository:
       }
     ]
   "member-access":
+    name: "meta.member.access.python"
     begin: "(\\.)\\s*(?!\\.)"
     end: '''
       (?x)
@@ -1167,6 +1168,7 @@ repository:
       "1":
         name: "entity.other.inherited-class.python"
   "member-access-class":
+    name: "meta.member.access.python"
     begin: "(\\.)\\s*(?!\\.)"
     end: "(?<=\\S)(?=\\W)|$"
     beginCaptures:
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 4fa597d1..ba24d9d1 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -614,6 +614,8 @@ it's probably control flow like:
       </dict>
       <key>member-access</key>
       <dict>
+        <key>name</key>
+        <string>meta.member.access.python</string>
         <key>begin</key>
         <string>(\.)\s*(?!\.)</string>
         <key>end</key>
@@ -1796,6 +1798,8 @@ it's probably control flow like:
       </dict>
       <key>member-access-class</key>
       <dict>
+        <key>name</key>
+        <string>meta.member.access.python</string>
         <key>begin</key>
         <string>(\.)\s*(?!\.)</string>
         <key>end</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index baf73a1c..7dbec777 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -433,6 +433,7 @@ repository:
         match: (?x) \b ([[:alpha:]_]\w*) \b
 
   member-access:
+    name: meta.member.access.python
     begin: (\.)\s*(?!\.)
     end: |
       (?x)
@@ -947,6 +948,7 @@ repository:
       '1': {name: entity.other.inherited-class.python}
 
   member-access-class:
+    name: meta.member.access.python
     begin: (\.)\s*(?!\.)
     end: (?<=\S)(?=\W)|$
     beginCaptures:
diff --git a/misc/scopes b/misc/scopes
index a49a024d..17a74a4a 100644
--- a/misc/scopes
+++ b/misc/scopes
@@ -75,6 +75,7 @@ meta.function.parameters.python
 meta.function.python
 meta.item-access.python
 meta.lambda-function.python
+meta.member.access.python
 meta.named.regexp
 meta.typehint.comment.python
 punctuation.character.set.begin.regexp
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 37e92940..d1c7466b 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -166,15 +166,15 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].value).toBe("some");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("__bases__");
-      expect(tokens[1][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[2][0].value).toBe("some");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
-      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("__class__");
-      expect(tokens[2][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[3][0].value).toBe("assert");
       expect(tokens[3][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
       expect(tokens[3][1].value).toBe(" ");
@@ -186,9 +186,9 @@ describe("Grammar Tests", function() {
       expect(tokens[5][0].value).toBe("__builtins__");
       expect(tokens[5][0].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[5][1].value).toBe(".");
-      expect(tokens[5][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[5][2].value).toBe("len");
-      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[6][0].value).toBe("print");
       expect(tokens[6][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
       expect(tokens[6][1].value).toBe("(");
@@ -200,219 +200,219 @@ describe("Grammar Tests", function() {
       expect(tokens[7][0].value).toBe("some");
       expect(tokens[7][0].scopes).toEqual(["source.python"]);
       expect(tokens[7][1].value).toBe(".");
-      expect(tokens[7][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[7][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[7][2].value).toBe("__dict__");
-      expect(tokens[7][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[7][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[8][0].value).toBe("some");
       expect(tokens[8][0].scopes).toEqual(["source.python"]);
       expect(tokens[8][1].value).toBe(".");
-      expect(tokens[8][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[8][2].value).toBe("__doc__");
-      expect(tokens[8][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[9][0].value).toBe("some");
       expect(tokens[9][0].scopes).toEqual(["source.python"]);
       expect(tokens[9][1].value).toBe(".");
-      expect(tokens[9][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[9][2].value).toBe("__file__");
-      expect(tokens[9][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[10][0].value).toBe("some");
       expect(tokens[10][0].scopes).toEqual(["source.python"]);
       expect(tokens[10][1].value).toBe(".");
-      expect(tokens[10][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[10][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[10][2].value).toBe("__members__");
-      expect(tokens[10][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[10][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[11][0].value).toBe("some");
       expect(tokens[11][0].scopes).toEqual(["source.python"]);
       expect(tokens[11][1].value).toBe(".");
-      expect(tokens[11][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[11][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[11][2].value).toBe("__metaclass__");
-      expect(tokens[11][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[11][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[12][0].value).toBe("some");
       expect(tokens[12][0].scopes).toEqual(["source.python"]);
       expect(tokens[12][1].value).toBe(".");
-      expect(tokens[12][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[12][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[12][2].value).toBe("__methods__");
-      expect(tokens[12][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[12][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[13][0].value).toBe("some");
       expect(tokens[13][0].scopes).toEqual(["source.python"]);
       expect(tokens[13][1].value).toBe(".");
-      expect(tokens[13][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[13][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[13][2].value).toBe("__module__");
-      expect(tokens[13][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[13][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[14][0].value).toBe("some");
       expect(tokens[14][0].scopes).toEqual(["source.python"]);
       expect(tokens[14][1].value).toBe(".");
-      expect(tokens[14][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[14][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[14][2].value).toBe("__mro__");
-      expect(tokens[14][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[14][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[15][0].value).toBe("some");
       expect(tokens[15][0].scopes).toEqual(["source.python"]);
       expect(tokens[15][1].value).toBe(".");
-      expect(tokens[15][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[15][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[15][2].value).toBe("__name__");
-      expect(tokens[15][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[15][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[16][0].value).toBe("some");
       expect(tokens[16][0].scopes).toEqual(["source.python"]);
       expect(tokens[16][1].value).toBe(".");
-      expect(tokens[16][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[16][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[16][2].value).toBe("__slots__");
-      expect(tokens[16][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[16][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[17][0].value).toBe("some");
       expect(tokens[17][0].scopes).toEqual(["source.python"]);
       expect(tokens[17][1].value).toBe(".");
-      expect(tokens[17][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[17][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[17][2].value).toBe("__subclasses__");
-      expect(tokens[17][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[17][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[18][0].value).toBe("some");
       expect(tokens[18][0].scopes).toEqual(["source.python"]);
       expect(tokens[18][1].value).toBe(".");
-      expect(tokens[18][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[18][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[18][2].value).toBe("__version__");
-      expect(tokens[18][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[18][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[19][0].value).toBe("some");
       expect(tokens[19][0].scopes).toEqual(["source.python"]);
       expect(tokens[19][1].value).toBe(".");
-      expect(tokens[19][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[19][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[19][2].value).toBe("__weakref__");
-      expect(tokens[19][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[19][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[20][0].value).toBe("some");
       expect(tokens[20][0].scopes).toEqual(["source.python"]);
       expect(tokens[20][1].value).toBe(".");
-      expect(tokens[20][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[20][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[20][2].value).toBe("__qualname__");
-      expect(tokens[20][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[20][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[21][0].value).toBe("some");
       expect(tokens[21][0].scopes).toEqual(["source.python"]);
       expect(tokens[21][1].value).toBe(".");
-      expect(tokens[21][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[21][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[21][2].value).toBe("__code__");
-      expect(tokens[21][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[21][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[22][0].value).toBe("some");
       expect(tokens[22][0].scopes).toEqual(["source.python"]);
       expect(tokens[22][1].value).toBe(".");
-      expect(tokens[22][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[22][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[22][2].value).toBe("__wrapped__");
-      expect(tokens[22][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[22][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[23][0].value).toBe("some");
       expect(tokens[23][0].scopes).toEqual(["source.python"]);
       expect(tokens[23][1].value).toBe(".");
-      expect(tokens[23][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[23][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[23][2].value).toBe("__signature__");
-      expect(tokens[23][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[23][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[24][0].value).toBe("some");
       expect(tokens[24][0].scopes).toEqual(["source.python"]);
       expect(tokens[24][1].value).toBe(".");
-      expect(tokens[24][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[24][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[24][2].value).toBe("__defaults__");
-      expect(tokens[24][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[24][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[25][0].value).toBe("some");
       expect(tokens[25][0].scopes).toEqual(["source.python"]);
       expect(tokens[25][1].value).toBe(".");
-      expect(tokens[25][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[25][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[25][2].value).toBe("__func__");
-      expect(tokens[25][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[25][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[26][0].value).toBe("some");
       expect(tokens[26][0].scopes).toEqual(["source.python"]);
       expect(tokens[26][1].value).toBe(".");
-      expect(tokens[26][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[26][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[26][2].value).toBe("__self__");
-      expect(tokens[26][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[26][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[27][0].value).toBe("some");
       expect(tokens[27][0].scopes).toEqual(["source.python"]);
       expect(tokens[27][1].value).toBe(".");
-      expect(tokens[27][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[27][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[27][2].value).toBe("__kwdefaults__");
-      expect(tokens[27][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[27][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[28][0].value).toBe("some");
       expect(tokens[28][0].scopes).toEqual(["source.python"]);
       expect(tokens[28][1].value).toBe(".");
-      expect(tokens[28][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[28][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[28][2].value).toBe("__matmul__");
-      expect(tokens[28][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[28][2].scopes).toEqual(["source.python","meta.member.access.python","support.function.magic.python"]);
       expect(tokens[29][0].value).toBe("some");
       expect(tokens[29][0].scopes).toEqual(["source.python"]);
       expect(tokens[29][1].value).toBe(".");
-      expect(tokens[29][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[29][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[29][2].value).toBe("__imatmul__");
-      expect(tokens[29][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[29][2].scopes).toEqual(["source.python","meta.member.access.python","support.function.magic.python"]);
       expect(tokens[30][0].value).toBe("some");
       expect(tokens[30][0].scopes).toEqual(["source.python"]);
       expect(tokens[30][1].value).toBe(".");
-      expect(tokens[30][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[30][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[30][2].value).toBe("__rmatmul__");
-      expect(tokens[30][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[30][2].scopes).toEqual(["source.python","meta.member.access.python","support.function.magic.python"]);
       expect(tokens[31][0].value).toBe("some");
       expect(tokens[31][0].scopes).toEqual(["source.python"]);
       expect(tokens[31][1].value).toBe(".");
-      expect(tokens[31][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[31][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[31][2].value).toBe("__annotations__");
-      expect(tokens[31][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[31][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[32][0].value).toBe("some");
       expect(tokens[32][0].scopes).toEqual(["source.python"]);
       expect(tokens[32][1].value).toBe(".");
-      expect(tokens[32][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[32][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[32][2].value).toBe("__init_subclass__");
-      expect(tokens[32][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[32][2].scopes).toEqual(["source.python","meta.member.access.python","support.function.magic.python"]);
       expect(tokens[33][0].value).toBe("some");
       expect(tokens[33][0].scopes).toEqual(["source.python"]);
       expect(tokens[33][1].value).toBe(".");
-      expect(tokens[33][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[33][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[33][2].value).toBe("__set_name__");
-      expect(tokens[33][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[33][2].scopes).toEqual(["source.python","meta.member.access.python","support.function.magic.python"]);
       expect(tokens[34][0].value).toBe("some");
       expect(tokens[34][0].scopes).toEqual(["source.python"]);
       expect(tokens[34][1].value).toBe(".");
-      expect(tokens[34][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[34][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[34][2].value).toBe("__fspath__");
-      expect(tokens[34][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[34][2].scopes).toEqual(["source.python","meta.member.access.python","support.function.magic.python"]);
       expect(tokens[35][0].value).toBe("some");
       expect(tokens[35][0].scopes).toEqual(["source.python"]);
       expect(tokens[35][1].value).toBe(".");
-      expect(tokens[35][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[35][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[35][2].value).toBe("__classcell__");
-      expect(tokens[35][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[35][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[36][0].value).toBe("some");
       expect(tokens[36][0].scopes).toEqual(["source.python"]);
       expect(tokens[36][1].value).toBe(".");
-      expect(tokens[36][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[36][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[36][2].value).toBe("__bytes__");
-      expect(tokens[36][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[36][2].scopes).toEqual(["source.python","meta.member.access.python","support.function.magic.python"]);
       expect(tokens[37][0].value).toBe("some");
       expect(tokens[37][0].scopes).toEqual(["source.python"]);
       expect(tokens[37][1].value).toBe(".");
-      expect(tokens[37][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[37][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[37][2].value).toBe("__spec__");
-      expect(tokens[37][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[37][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[38][0].value).toBe("some");
       expect(tokens[38][0].scopes).toEqual(["source.python"]);
       expect(tokens[38][1].value).toBe(".");
-      expect(tokens[38][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[38][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[38][2].value).toBe("__path__");
-      expect(tokens[38][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[38][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[39][0].value).toBe("some");
       expect(tokens[39][0].scopes).toEqual(["source.python"]);
       expect(tokens[39][1].value).toBe(".");
-      expect(tokens[39][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[39][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[39][2].value).toBe("__prepare__");
-      expect(tokens[39][2].scopes).toEqual(["source.python","support.function.magic.python"]);
+      expect(tokens[39][2].scopes).toEqual(["source.python","meta.member.access.python","support.function.magic.python"]);
       expect(tokens[40][0].value).toBe("some");
       expect(tokens[40][0].scopes).toEqual(["source.python"]);
       expect(tokens[40][1].value).toBe(".");
-      expect(tokens[40][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[40][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[40][2].value).toBe("__package__");
-      expect(tokens[40][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[40][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[41][0].value).toBe("some");
       expect(tokens[41][0].scopes).toEqual(["source.python"]);
       expect(tokens[41][1].value).toBe(".");
-      expect(tokens[41][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[41][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[41][2].value).toBe("__traceback__");
-      expect(tokens[41][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[41][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[42][0].value).toBe("some");
       expect(tokens[42][0].scopes).toEqual(["source.python"]);
       expect(tokens[42][1].value).toBe(".");
-      expect(tokens[42][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[42][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[42][2].value).toBe("__notspecial__");
-      expect(tokens[42][2].scopes).toEqual(["source.python"]);
+      expect(tokens[42][2].scopes).toEqual(["source.python","meta.member.access.python"]);
     });
 
   it("test/builtins/builtins4.py", 
@@ -421,39 +421,39 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("some");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("int");
-      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[1][0].value).toBe("some");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("sum");
-      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[2][0].value).toBe("some");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
-      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("super");
-      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[3][0].value).toBe("some");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("unicode");
-      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[4][0].value).toBe("some");
       expect(tokens[4][0].scopes).toEqual(["source.python"]);
       expect(tokens[4][1].value).toBe(".");
-      expect(tokens[4][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[4][2].value).toBe("foo");
-      expect(tokens[4][2].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[5][0].value).toBe("some");
       expect(tokens[5][0].scopes).toEqual(["source.python"]);
       expect(tokens[5][1].value).toBe(".");
-      expect(tokens[5][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[5][2].value).toBe("Exception");
-      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.member.access.python"]);
     });
 
   it("test/builtins/builtins5.py", 
@@ -462,37 +462,37 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("some");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe(" ");
-      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[0][3].value).toBe("True");
-      expect(tokens[0][3].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.member.access.python","keyword.illegal.name.python"]);
       expect(tokens[1][0].value).toBe("some");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe(" ");
-      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[1][3].value).toBe("\\");
-      expect(tokens[1][3].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.continuation.line.python"]);
       expect(tokens[1][4].value).toBe("");
-      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[2][0].value).toBe("    ");
-      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[2][1].value).toBe("True");
-      expect(tokens[2][1].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.member.access.python","keyword.illegal.name.python"]);
       expect(tokens[3][0].value).toBe("True");
       expect(tokens[3][0].scopes).toEqual(["source.python","constant.language.python"]);
       expect(tokens[4][0].value).toBe("some");
       expect(tokens[4][0].scopes).toEqual(["source.python"]);
       expect(tokens[4][1].value).toBe(".");
-      expect(tokens[4][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[4][2].value).toBe("");
-      expect(tokens[4][2].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[5][0].value).toBe("    ");
-      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[5][1].value).toBe("True");
-      expect(tokens[5][1].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.member.access.python","keyword.illegal.name.python"]);
     });
 
   it("test/builtins/builtins6.py", 
@@ -674,31 +674,31 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("foo");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("class");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","keyword.control.flow.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","keyword.control.flow.python"]);
       expect(tokens[0][3].value).toBe("(");
-      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][4].value).toBe("a");
-      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[0][5].value).toBe(")");
-      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[1][0].value).toBe("foo");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("and");
-      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","keyword.control.flow.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","keyword.control.flow.python"]);
       expect(tokens[1][3].value).toBe("(");
-      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[1][4].value).toBe(")");
-      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[2][0].value).toBe("foo");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
-      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("if");
-      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.member.access.python","keyword.control.flow.python"]);
     });
 
   it("test/calls/call4.py", 
@@ -707,9 +707,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("foo");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("1");
-      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[1][0].value).toBe("foo");
       expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[1][1].value).toBe("(");
@@ -735,9 +735,9 @@ describe("Grammar Tests", function() {
       expect(tokens[2][0].value).toBe("foo");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
-      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("None");
-      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.member.access.python","keyword.illegal.name.python"]);
       expect(tokens[2][3].value).toBe(" ");
       expect(tokens[2][3].scopes).toEqual(["source.python"]);
       expect(tokens[2][4].value).toBe("and");
@@ -747,13 +747,13 @@ describe("Grammar Tests", function() {
       expect(tokens[2][6].value).toBe("foo");
       expect(tokens[2][6].scopes).toEqual(["source.python"]);
       expect(tokens[2][7].value).toBe(".");
-      expect(tokens[2][7].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][8].value).toBe("None");
-      expect(tokens[2][8].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.member.access.python","keyword.illegal.name.python"]);
       expect(tokens[2][9].value).toBe(".");
-      expect(tokens[2][9].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][9].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][10].value).toBe("baz");
-      expect(tokens[2][10].scopes).toEqual(["source.python"]);
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.member.access.python"]);
     });
 
   it("test/calls/call5.py", 
@@ -840,79 +840,79 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("foo");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("__class__");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.variable.magic.python"]);
       expect(tokens[0][3].value).toBe(" ");
-      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python"]);
       expect(tokens[0][4].value).toBe("(");
-      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][5].value).toBe("foo");
-      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[0][6].value).toBe("=");
-      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[0][7].value).toBe("bar");
-      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[0][8].value).toBe(")");
-      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[1][0].value).toBe("foo");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("__class__");
-      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.variable.magic.python"]);
       expect(tokens[1][3].value).toBe("(");
-      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[1][4].value).toBe("foo");
-      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[1][5].value).toBe("=");
-      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[1][6].value).toBe("bar");
-      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[1][7].value).toBe(")");
-      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[2][0].value).toBe("foo");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
-      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("__add__");
-      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[2][3].value).toBe(" ");
-      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python"]);
       expect(tokens[2][4].value).toBe("(");
-      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[2][5].value).toBe("foo");
-      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[2][6].value).toBe("=");
-      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[2][7].value).toBe("bar");
-      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[2][8].value).toBe(")");
-      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[3][0].value).toBe("foo");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("__add__");
-      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[3][3].value).toBe("(");
-      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[3][4].value).toBe("foo");
-      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[3][5].value).toBe("=");
-      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[3][6].value).toBe("bar");
-      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[3][7].value).toBe(")");
-      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[4][0].value).toBe("");
       expect(tokens[4][0].scopes).toEqual(["source.python"]);
       expect(tokens[5][0].value).toBe("foo");
       expect(tokens[5][0].scopes).toEqual(["source.python"]);
       expect(tokens[5][1].value).toBe(".");
-      expect(tokens[5][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[5][2].value).toBe("__class__");
-      expect(tokens[5][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[5][3].value).toBe(" ");
       expect(tokens[5][3].scopes).toEqual(["source.python"]);
       expect(tokens[5][4].value).toBe("1");
@@ -925,79 +925,79 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("foo");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe(" ");
-      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[0][3].value).toBe("__class__");
-      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.variable.magic.python"]);
       expect(tokens[0][4].value).toBe("(");
-      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][5].value).toBe("foo");
-      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[0][6].value).toBe("=");
-      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[0][7].value).toBe("bar");
-      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[0][8].value).toBe(")");
-      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[1][0].value).toBe("foo");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe(" ");
-      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[1][3].value).toBe("__class__");
-      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","support.variable.magic.python"]);
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.variable.magic.python"]);
       expect(tokens[1][4].value).toBe(" ");
-      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python"]);
       expect(tokens[1][5].value).toBe("(");
-      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[1][6].value).toBe("foo");
-      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[1][7].value).toBe("=");
-      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[1][8].value).toBe("bar");
-      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[1][9].value).toBe(")");
-      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[2][0].value).toBe("foo");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
-      expect(tokens[2][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe(" ");
-      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[2][3].value).toBe("__add__");
-      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[2][4].value).toBe(" ");
-      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function-call.python"]);
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python"]);
       expect(tokens[2][5].value).toBe("(");
-      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[2][6].value).toBe("foo");
-      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[2][7].value).toBe("=");
-      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[2][8].value).toBe("bar");
-      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[2][9].value).toBe(")");
-      expect(tokens[2][9].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[3][0].value).toBe("foo");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe(" ");
-      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[3][3].value).toBe("__add__");
-      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[3][4].value).toBe("(");
-      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[3][5].value).toBe("foo");
-      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[3][6].value).toBe("=");
-      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[3][7].value).toBe("bar");
-      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[3][8].value).toBe(")");
-      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
     });
 
   it("test/calls/call9.py", 
@@ -1109,9 +1109,9 @@ describe("Grammar Tests", function() {
       expect(tokens[6][3].value).toBe("sys");
       expect(tokens[6][3].scopes).toEqual(["source.python"]);
       expect(tokens[6][4].value).toBe(".");
-      expect(tokens[6][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[6][5].value).toBe("stderr");
-      expect(tokens[6][5].scopes).toEqual(["source.python"]);
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[6][6].value).toBe(",");
       expect(tokens[6][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
       expect(tokens[6][7].value).toBe(" ");
@@ -1143,9 +1143,9 @@ describe("Grammar Tests", function() {
       expect(tokens[7][9].value).toBe("sys");
       expect(tokens[7][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[7][10].value).toBe(".");
-      expect(tokens[7][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.period.python"]);
+      expect(tokens[7][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[7][11].value).toBe("stderr");
-      expect(tokens[7][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[7][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.member.access.python"]);
       expect(tokens[7][12].value).toBe(")");
       expect(tokens[7][12].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[8][0].value).toBe("print");
@@ -1314,9 +1314,9 @@ describe("Grammar Tests", function() {
       expect(tokens[2][1].value).toBe("self");
       expect(tokens[2][1].scopes).toEqual(["source.python","variable.language.special.self.python"]);
       expect(tokens[2][2].value).toBe(".");
-      expect(tokens[2][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][3].value).toBe("a");
-      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[2][4].value).toBe(" ");
       expect(tokens[2][4].scopes).toEqual(["source.python"]);
       expect(tokens[2][5].value).toBe("=");
@@ -1330,9 +1330,9 @@ describe("Grammar Tests", function() {
       expect(tokens[3][1].value).toBe("self");
       expect(tokens[3][1].scopes).toEqual(["source.python","variable.language.special.self.python"]);
       expect(tokens[3][2].value).toBe(".");
-      expect(tokens[3][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][3].value).toBe("b");
-      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[3][4].value).toBe(" ");
       expect(tokens[3][4].scopes).toEqual(["source.python"]);
       expect(tokens[3][5].value).toBe("=");
@@ -1364,9 +1364,9 @@ describe("Grammar Tests", function() {
       expect(tokens[6][1].value).toBe("a");
       expect(tokens[6][1].scopes).toEqual(["source.python"]);
       expect(tokens[6][2].value).toBe(".");
-      expect(tokens[6][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[6][3].value).toBe("self");
-      expect(tokens[6][3].scopes).toEqual(["source.python"]);
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[6][4].value).toBe(" ");
       expect(tokens[6][4].scopes).toEqual(["source.python"]);
       expect(tokens[6][5].value).toBe("=");
@@ -1380,13 +1380,13 @@ describe("Grammar Tests", function() {
       expect(tokens[7][1].value).toBe("a");
       expect(tokens[7][1].scopes).toEqual(["source.python"]);
       expect(tokens[7][2].value).toBe(".");
-      expect(tokens[7][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[7][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[7][3].value).toBe("self");
-      expect(tokens[7][3].scopes).toEqual(["source.python"]);
+      expect(tokens[7][3].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[7][4].value).toBe(".");
-      expect(tokens[7][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[7][4].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[7][5].value).toBe("bar");
-      expect(tokens[7][5].scopes).toEqual(["source.python"]);
+      expect(tokens[7][5].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[7][6].value).toBe(" ");
       expect(tokens[7][6].scopes).toEqual(["source.python"]);
       expect(tokens[7][7].value).toBe("=");
@@ -1461,9 +1461,9 @@ describe("Grammar Tests", function() {
       expect(tokens[3][1].value).toBe("cls");
       expect(tokens[3][1].scopes).toEqual(["source.python","variable.language.special.cls.python"]);
       expect(tokens[3][2].value).toBe(".");
-      expect(tokens[3][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][3].value).toBe("a");
-      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[3][4].value).toBe(" ");
       expect(tokens[3][4].scopes).toEqual(["source.python"]);
       expect(tokens[3][5].value).toBe("=");
@@ -1477,9 +1477,9 @@ describe("Grammar Tests", function() {
       expect(tokens[4][1].value).toBe("cls");
       expect(tokens[4][1].scopes).toEqual(["source.python","variable.language.special.cls.python"]);
       expect(tokens[4][2].value).toBe(".");
-      expect(tokens[4][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[4][3].value).toBe("b");
-      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[4][4].value).toBe(" ");
       expect(tokens[4][4].scopes).toEqual(["source.python"]);
       expect(tokens[4][5].value).toBe("=");
@@ -1523,9 +1523,9 @@ describe("Grammar Tests", function() {
       expect(tokens[8][1].value).toBe("a");
       expect(tokens[8][1].scopes).toEqual(["source.python"]);
       expect(tokens[8][2].value).toBe(".");
-      expect(tokens[8][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[8][3].value).toBe("cls");
-      expect(tokens[8][3].scopes).toEqual(["source.python"]);
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[8][4].value).toBe(" ");
       expect(tokens[8][4].scopes).toEqual(["source.python"]);
       expect(tokens[8][5].value).toBe("=");
@@ -1539,13 +1539,13 @@ describe("Grammar Tests", function() {
       expect(tokens[9][1].value).toBe("a");
       expect(tokens[9][1].scopes).toEqual(["source.python"]);
       expect(tokens[9][2].value).toBe(".");
-      expect(tokens[9][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[9][3].value).toBe("cls");
-      expect(tokens[9][3].scopes).toEqual(["source.python"]);
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[9][4].value).toBe(".");
-      expect(tokens[9][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[9][4].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[9][5].value).toBe("__name__");
-      expect(tokens[9][5].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[9][5].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
       expect(tokens[10][0].value).toBe("        ");
       expect(tokens[10][0].scopes).toEqual(["source.python"]);
       expect(tokens[10][1].value).toBe("cls");
@@ -1605,9 +1605,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].value).toBe("f");
       expect(tokens[0][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[0][5].value).toBe(".");
-      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.period.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][6].value).toBe("Exception");
-      expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.member.access.python","entity.other.inherited-class.python"]);
       expect(tokens[0][7].value).toBe(",");
       expect(tokens[0][7].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
       expect(tokens[0][8].value).toBe(" ");
@@ -1615,9 +1615,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][9].value).toBe("f");
       expect(tokens[0][9].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[0][10].value).toBe(".");
-      expect(tokens[0][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.period.python"]);
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][11].value).toBe("type");
-      expect(tokens[0][11].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.member.access.python","entity.other.inherited-class.python"]);
       expect(tokens[0][12].value).toBe(",");
       expect(tokens[0][12].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
       expect(tokens[0][13].value).toBe(" ");
@@ -1631,9 +1631,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][17].value).toBe("Exception");
       expect(tokens[0][17].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","support.type.exception.python"]);
       expect(tokens[0][18].value).toBe(".");
-      expect(tokens[0][18].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.period.python"]);
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][19].value).toBe("a");
-      expect(tokens[0][19].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.member.access.python","entity.other.inherited-class.python"]);
       expect(tokens[0][20].value).toBe(",");
       expect(tokens[0][20].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
       expect(tokens[0][21].value).toBe(" ");
@@ -1758,9 +1758,9 @@ describe("Grammar Tests", function() {
       expect(tokens[2][4].value).toBe("Foo");
       expect(tokens[2][4].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[2][5].value).toBe(".");
-      expect(tokens[2][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.period.python"]);
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][6].value).toBe("Bar");
-      expect(tokens[2][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.member.access.python","entity.other.inherited-class.python"]);
       expect(tokens[2][7].value).toBe(",");
       expect(tokens[2][7].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.inheritance.python"]);
       expect(tokens[2][8].value).toBe(" ");
@@ -1768,9 +1768,9 @@ describe("Grammar Tests", function() {
       expect(tokens[2][9].value).toBe("Bar");
       expect(tokens[2][9].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
       expect(tokens[2][10].value).toBe(".");
-      expect(tokens[2][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","punctuation.separator.period.python"]);
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][11].value).toBe("name");
-      expect(tokens[2][11].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","entity.other.inherited-class.python"]);
+      expect(tokens[2][11].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","meta.member.access.python","entity.other.inherited-class.python"]);
       expect(tokens[2][12].value).toBe("=");
       expect(tokens[2][12].scopes).toEqual(["source.python","meta.class.python","meta.class.inheritance.python","keyword.operator.assignment.python"]);
       expect(tokens[2][13].value).toBe("{");
@@ -2046,19 +2046,19 @@ describe("Grammar Tests", function() {
       expect(tokens[2][3].value).toBe(")");
       expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[2][4].value).toBe(".");
-      expect(tokens[2][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][5].value).toBe("__init__");
-      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[2][6].value).toBe("(");
-      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[2][7].value).toBe("foo");
-      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[2][8].value).toBe("=");
-      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[2][9].value).toBe("1");
-      expect(tokens[2][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[2][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
       expect(tokens[2][10].value).toBe(")");
-      expect(tokens[2][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[3][0].value).toBe("        ");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
       expect(tokens[3][1].value).toBe("super");
@@ -2068,21 +2068,21 @@ describe("Grammar Tests", function() {
       expect(tokens[3][3].value).toBe(")");
       expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[3][4].value).toBe(".");
-      expect(tokens[3][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][5].value).toBe(" ");
-      expect(tokens[3][5].scopes).toEqual(["source.python"]);
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[3][6].value).toBe("__init__");
-      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[3][7].value).toBe("(");
-      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[3][8].value).toBe("foo");
-      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[3][9].value).toBe("=");
-      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[3][10].value).toBe("1");
-      expect(tokens[3][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[3][10].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
       expect(tokens[3][11].value).toBe(")");
-      expect(tokens[3][11].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][11].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[4][0].value).toBe("        ");
       expect(tokens[4][0].scopes).toEqual(["source.python"]);
       expect(tokens[4][1].value).toBe("super");
@@ -2092,25 +2092,25 @@ describe("Grammar Tests", function() {
       expect(tokens[4][3].value).toBe(")");
       expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[4][4].value).toBe(".");
-      expect(tokens[4][4].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[4][5].value).toBe(" ");
-      expect(tokens[4][5].scopes).toEqual(["source.python"]);
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[4][6].value).toBe("\\");
-      expect(tokens[4][6].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.continuation.line.python"]);
       expect(tokens[4][7].value).toBe("");
-      expect(tokens[4][7].scopes).toEqual(["source.python"]);
+      expect(tokens[4][7].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[5][0].value).toBe("__init__");
-      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[5][1].value).toBe("(");
-      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[5][2].value).toBe("foo");
-      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[5][3].value).toBe("=");
-      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[5][4].value).toBe("1");
-      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
       expect(tokens[5][5].value).toBe(")");
-      expect(tokens[5][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[6][0].value).toBe("        ");
       expect(tokens[6][0].scopes).toEqual(["source.python"]);
       expect(tokens[6][1].value).toBe("__init__");
@@ -2132,19 +2132,19 @@ describe("Grammar Tests", function() {
       expect(tokens[8][1].value).toBe("foo");
       expect(tokens[8][1].scopes).toEqual(["source.python"]);
       expect(tokens[8][2].value).toBe(".");
-      expect(tokens[8][2].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[8][3].value).toBe("__init__");
-      expect(tokens[8][3].scopes).toEqual(["source.python","meta.function-call.python","support.function.magic.python"]);
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","support.function.magic.python"]);
       expect(tokens[8][4].value).toBe("(");
-      expect(tokens[8][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[8][5].value).toBe("bar");
-      expect(tokens[8][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[8][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[8][6].value).toBe("=");
-      expect(tokens[8][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[8][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[8][7].value).toBe("1");
-      expect(tokens[8][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[8][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
       expect(tokens[8][8].value).toBe(")");
-      expect(tokens[8][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[8][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[9][0].value).toBe("        ");
       expect(tokens[9][0].scopes).toEqual(["source.python"]);
       expect(tokens[9][1].value).toBe("__init__");
@@ -5069,17 +5069,17 @@ describe("Grammar Tests", function() {
       expect(tokens[0][8].value).toBe("QQQ");
       expect(tokens[0][8].scopes).toEqual(["source.python","constant.other.caps.python"]);
       expect(tokens[0][9].value).toBe(".");
-      expect(tokens[0][9].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][10].value).toBe("bar");
-      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[0][11].value).toBe(" ");
       expect(tokens[0][11].scopes).toEqual(["source.python"]);
       expect(tokens[0][12].value).toBe("baz");
       expect(tokens[0][12].scopes).toEqual(["source.python"]);
       expect(tokens[0][13].value).toBe(".");
-      expect(tokens[0][13].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][14].value).toBe("AA_a");
-      expect(tokens[0][14].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.member.access.python","constant.other.caps.python"]);
       expect(tokens[0][15].value).toBe(" ");
       expect(tokens[0][15].scopes).toEqual(["source.python"]);
       expect(tokens[0][16].value).toBe("_AAA");
@@ -5089,9 +5089,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][18].value).toBe("foo");
       expect(tokens[0][18].scopes).toEqual(["source.python"]);
       expect(tokens[0][19].value).toBe(".");
-      expect(tokens[0][19].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][20].value).toBe("_AAA");
-      expect(tokens[0][20].scopes).toEqual(["source.python","constant.other.caps.python"]);
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.member.access.python","constant.other.caps.python"]);
       expect(tokens[1][0].value).toBe("QQQq");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(" ");
@@ -5103,13 +5103,13 @@ describe("Grammar Tests", function() {
       expect(tokens[1][4].value).toBe("self");
       expect(tokens[1][4].scopes).toEqual(["source.python","variable.language.special.self.python"]);
       expect(tokens[1][5].value).toBe(".");
-      expect(tokens[1][5].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[1][6].value).toBe("FOOO");
-      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[1][7].value).toBe("(");
-      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[1][8].value).toBe(")");
-      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[1][9].value).toBe(" ");
       expect(tokens[1][9].scopes).toEqual(["source.python"]);
       expect(tokens[1][10].value).toBe("_");
@@ -5373,9 +5373,9 @@ describe("Grammar Tests", function() {
       expect(tokens[3][0].value).toBe("...");
       expect(tokens[3][0].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("__class__");
-      expect(tokens[3][2].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
     });
 
   it("test/expressions/expr11.py", 
@@ -5392,19 +5392,19 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].value).toBe("self");
       expect(tokens[0][4].scopes).toEqual(["source.python","variable.language.special.self.python"]);
       expect(tokens[0][5].value).toBe(".");
-      expect(tokens[0][5].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][6].value).toBe("some_list");
-      expect(tokens[0][6].scopes).toEqual(["source.python","meta.item-access.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.member.access.python","meta.item-access.python"]);
       expect(tokens[0][7].value).toBe("[");
-      expect(tokens[0][7].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.member.access.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][8].value).toBe("1");
-      expect(tokens[0][8].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.member.access.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
       expect(tokens[0][9].value).toBe(":");
-      expect(tokens[0][9].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","punctuation.separator.slice.python"]);
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.member.access.python","meta.item-access.python","meta.item-access.arguments.python","punctuation.separator.slice.python"]);
       expect(tokens[0][10].value).toBe("2");
-      expect(tokens[0][10].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.member.access.python","meta.item-access.python","meta.item-access.arguments.python","constant.numeric.dec.python"]);
       expect(tokens[0][11].value).toBe("]");
-      expect(tokens[0][11].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.member.access.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
     });
 
   it("test/expressions/expr12.py", 
@@ -5468,9 +5468,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("foofrom");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("something");
-      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python"]);
     });
 
   it("test/expressions/expr16.py", 
@@ -5539,15 +5539,15 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("a");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("Exception");
-      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[1][0].value).toBe("Exception");
       expect(tokens[1][0].scopes).toEqual(["source.python","support.type.exception.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("a");
-      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python"]);
     });
 
   it("test/expressions/expr19.py", 
@@ -5556,9 +5556,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("a");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe(" ");
-      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[0][3].value).toBe("#");
       expect(tokens[0][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[0][4].value).toBe("foo");
@@ -5566,9 +5566,9 @@ describe("Grammar Tests", function() {
       expect(tokens[1][0].value).toBe("a");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
-      expect(tokens[1][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("");
-      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[2][0].value).toBe("#");
       expect(tokens[2][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[2][1].value).toBe("foo");
@@ -5576,13 +5576,13 @@ describe("Grammar Tests", function() {
       expect(tokens[3][0].value).toBe("a");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe(" ");
-      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[3][3].value).toBe("\\");
-      expect(tokens[3][3].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.continuation.line.python"]);
       expect(tokens[3][4].value).toBe("");
-      expect(tokens[3][4].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[4][0].value).toBe("#");
       expect(tokens[4][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[4][1].value).toBe("foo");
@@ -5590,9 +5590,9 @@ describe("Grammar Tests", function() {
       expect(tokens[5][0].value).toBe("a");
       expect(tokens[5][0].scopes).toEqual(["source.python"]);
       expect(tokens[5][1].value).toBe(".");
-      expect(tokens[5][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[5][2].value).toBe(" ");
-      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[5][3].value).toBe("'");
       expect(tokens[5][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[5][4].value).toBe("bar");
@@ -5602,9 +5602,9 @@ describe("Grammar Tests", function() {
       expect(tokens[6][0].value).toBe("a");
       expect(tokens[6][0].scopes).toEqual(["source.python"]);
       expect(tokens[6][1].value).toBe(".");
-      expect(tokens[6][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[6][2].value).toBe("");
-      expect(tokens[6][2].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[7][0].value).toBe("'");
       expect(tokens[7][0].scopes).toEqual(["source.python","string.quoted.docstring.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[7][1].value).toBe("bar");
@@ -5614,19 +5614,19 @@ describe("Grammar Tests", function() {
       expect(tokens[8][0].value).toBe("a");
       expect(tokens[8][0].scopes).toEqual(["source.python"]);
       expect(tokens[8][1].value).toBe(".");
-      expect(tokens[8][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[8][2].value).toBe(" ");
-      expect(tokens[8][2].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[8][3].value).toBe("\\");
-      expect(tokens[8][3].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.continuation.line.python"]);
       expect(tokens[8][4].value).toBe("");
-      expect(tokens[8][4].scopes).toEqual(["source.python"]);
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.member.access.python"]);
       expect(tokens[9][0].value).toBe("'");
-      expect(tokens[9][0].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[9][0].scopes).toEqual(["source.python","meta.member.access.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[9][1].value).toBe("bar");
-      expect(tokens[9][1].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.member.access.python","string.quoted.single.python"]);
       expect(tokens[9][2].value).toBe("'");
-      expect(tokens[9][2].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.member.access.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
     });
 
   it("test/expressions/expr2.py", 
@@ -5999,9 +5999,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("a");
       expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("True");
-      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python","keyword.illegal.name.python"]);
       expect(tokens[0][3].value).toBe(" ");
       expect(tokens[0][3].scopes).toEqual(["source.python"]);
       expect(tokens[0][4].value).toBe("=");
@@ -6011,9 +6011,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][6].value).toBe("b");
       expect(tokens[0][6].scopes).toEqual(["source.python"]);
       expect(tokens[0][7].value).toBe(".");
-      expect(tokens[0][7].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][8].value).toBe("False");
-      expect(tokens[0][8].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.member.access.python","keyword.illegal.name.python"]);
       expect(tokens[0][9].value).toBe(" ");
       expect(tokens[0][9].scopes).toEqual(["source.python"]);
       expect(tokens[0][10].value).toBe("=");
@@ -6023,9 +6023,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][12].value).toBe("d");
       expect(tokens[0][12].scopes).toEqual(["source.python"]);
       expect(tokens[0][13].value).toBe(".");
-      expect(tokens[0][13].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][14].value).toBe("None");
-      expect(tokens[0][14].scopes).toEqual(["source.python","keyword.illegal.name.python"]);
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.member.access.python","keyword.illegal.name.python"]);
     });
 
   it("test/expressions/expr8.py", 
@@ -6354,71 +6354,71 @@ describe("Grammar Tests", function() {
       expect(tokens[0][0].value).toBe("self");
       expect(tokens[0][0].scopes).toEqual(["source.python","variable.language.special.self.python"]);
       expect(tokens[0][1].value).toBe(".");
-      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("assertEqual");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[0][3].value).toBe("(");
-      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][4].value).toBe("f");
-      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
       expect(tokens[0][5].value).toBe("'");
-      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
       expect(tokens[0][6].value).toBe("{");
-      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][7].value).toBe("10");
-      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
       expect(tokens[0][8].value).toBe(":");
-      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][9].value).toBe("#");
-      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][10].value).toBe("{");
-      expect(tokens[0][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][11].value).toBe("3");
-      expect(tokens[0][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
       expect(tokens[0][12].value).toBe(" ");
-      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
       expect(tokens[0][13].value).toBe("!=");
-      expect(tokens[0][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","keyword.operator.comparison.python"]);
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","keyword.operator.comparison.python"]);
       expect(tokens[0][14].value).toBe(" ");
-      expect(tokens[0][14].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
       expect(tokens[0][15].value).toBe("{");
-      expect(tokens[0][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","punctuation.definition.dict.begin.python"]);
       expect(tokens[0][16].value).toBe("4");
-      expect(tokens[0][16].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
       expect(tokens[0][17].value).toBe(":");
-      expect(tokens[0][17].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","punctuation.separator.dict.python"]);
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","punctuation.separator.dict.python"]);
       expect(tokens[0][18].value).toBe("5");
-      expect(tokens[0][18].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.numeric.dec.python"]);
       expect(tokens[0][19].value).toBe("}");
-      expect(tokens[0][19].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","punctuation.definition.dict.end.python"]);
       expect(tokens[0][20].value).toBe(" ");
-      expect(tokens[0][20].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
       expect(tokens[0][21].value).toBe("and");
-      expect(tokens[0][21].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","keyword.operator.logical.python"]);
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","keyword.operator.logical.python"]);
       expect(tokens[0][22].value).toBe(" ");
-      expect(tokens[0][22].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
       expect(tokens[0][23].value).toBe("width");
-      expect(tokens[0][23].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
       expect(tokens[0][24].value).toBe("}");
-      expect(tokens[0][24].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][24].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][25].value).toBe("x");
-      expect(tokens[0][25].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][25].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][26].value).toBe("}");
-      expect(tokens[0][26].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][26].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][27].value).toBe("'");
-      expect(tokens[0][27].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[0][27].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
       expect(tokens[0][28].value).toBe(",");
-      expect(tokens[0][28].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[0][28].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
       expect(tokens[0][29].value).toBe(" ");
-      expect(tokens[0][29].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[0][29].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[0][30].value).toBe("'");
-      expect(tokens[0][30].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][30].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
       expect(tokens[0][31].value).toBe("       0xa");
-      expect(tokens[0][31].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[0][31].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
       expect(tokens[0][32].value).toBe("'");
-      expect(tokens[0][32].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][32].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[0][33].value).toBe(")");
-      expect(tokens[0][33].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][33].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
     });
 
   it("test/fstrings/empty1.py", 
@@ -7463,9 +7463,9 @@ describe("Grammar Tests", function() {
       expect(tokens[0][19].value).toBe("fo");
       expect(tokens[0][19].scopes).toEqual(["source.python","meta.fstring.python"]);
       expect(tokens[0][20].value).toBe(".");
-      expect(tokens[0][20].scopes).toEqual(["source.python","meta.fstring.python","punctuation.separator.period.python"]);
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.fstring.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][21].value).toBe("__add__");
-      expect(tokens[0][21].scopes).toEqual(["source.python","meta.fstring.python","support.function.magic.python"]);
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.fstring.python","meta.member.access.python","support.function.magic.python"]);
       expect(tokens[0][22].value).toBe("!s");
       expect(tokens[0][22].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
       expect(tokens[0][23].value).toBe("}");
@@ -10044,19 +10044,19 @@ describe("Grammar Tests", function() {
       expect(tokens[4][7].value).toBe(")");
       expect(tokens[4][7].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
       expect(tokens[4][8].value).toBe(".");
-      expect(tokens[4][8].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[4][8].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[4][9].value).toBe("fuuuu");
-      expect(tokens[4][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[4][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[4][10].value).toBe("(");
-      expect(tokens[4][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[4][10].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[4][11].value).toBe("baz");
-      expect(tokens[4][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[4][11].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[4][12].value).toBe("=");
-      expect(tokens[4][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][12].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[4][13].value).toBe("1");
-      expect(tokens[4][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[4][13].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
       expect(tokens[4][14].value).toBe(")");
-      expect(tokens[4][14].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[4][14].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[5][0].value).toBe("#");
       expect(tokens[5][0].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[5][1].value).toBe(" we recover just fine");
@@ -11632,325 +11632,325 @@ describe("Grammar Tests", function() {
       expect(tokens[2][4].value).toBe("re");
       expect(tokens[2][4].scopes).toEqual(["source.python"]);
       expect(tokens[2][5].value).toBe(".");
-      expect(tokens[2][5].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][6].value).toBe("compile");
-      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[2][7].value).toBe("(");
-      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[2][8].value).toBe("r");
-      expect(tokens[2][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
       expect(tokens[2][9].value).toBe("\"\"\"");
-      expect(tokens[2][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
       expect(tokens[3][0].value).toBe("    ");
-      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[3][1].value).toBe("(?x)");
-      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.modifier.flag.regexp"]);
       expect(tokens[3][2].value).toBe("                           ");
-      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[3][3].value).toBe("#");
-      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[3][4].value).toBe(" This is a verbose pattern");
-      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
       expect(tokens[4][0].value).toBe("    ");
-      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[4][1].value).toBe("\\s");
-      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
       expect(tokens[4][2].value).toBe("*");
-      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
       expect(tokens[4][3].value).toBe("                            ");
-      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[4][4].value).toBe("#");
-      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[4][5].value).toBe(" Optional whitespace at start of cookie");
-      expect(tokens[4][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
       expect(tokens[5][0].value).toBe("    ");
-      expect(tokens[5][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[5][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[5][1].value).toBe("(");
-      expect(tokens[5][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[5][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"]);
       expect(tokens[5][2].value).toBe("?P<key>");
-      expect(tokens[5][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","entity.name.tag.named.group.regexp"]);
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","entity.name.tag.named.group.regexp"]);
       expect(tokens[5][3].value).toBe("                       ");
-      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[5][4].value).toBe("#");
-      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[5][5].value).toBe(" Start of group 'key'");
-      expect(tokens[5][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
       expect(tokens[6][0].value).toBe("    ");
-      expect(tokens[6][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[6][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[6][1].value).toBe("[");
-      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
       expect(tokens[6][2].value).toBe("\"\"\"");
-      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
       expect(tokens[6][3].value).toBe(" ");
-      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[6][4].value).toBe("+");
-      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
       expect(tokens[6][5].value).toBe(" ");
-      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[6][6].value).toBe("_LegalKeyChars");
-      expect(tokens[6][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[6][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[6][7].value).toBe(" ");
-      expect(tokens[6][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[6][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[6][8].value).toBe("+");
-      expect(tokens[6][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[6][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
       expect(tokens[6][9].value).toBe(" ");
-      expect(tokens[6][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[6][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[6][10].value).toBe("r");
-      expect(tokens[6][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[6][10].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
       expect(tokens[6][11].value).toBe("\"\"\"");
-      expect(tokens[6][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[6][11].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
       expect(tokens[6][12].value).toBe("]");
-      expect(tokens[6][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[6][12].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[6][13].value).toBe("+?");
-      expect(tokens[6][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[6][13].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
       expect(tokens[6][14].value).toBe("   ");
-      expect(tokens[6][14].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[6][14].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[6][15].value).toBe("#");
-      expect(tokens[6][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[6][15].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[6][16].value).toBe(" Any word of at least one letter");
-      expect(tokens[6][16].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[6][16].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
       expect(tokens[7][0].value).toBe("    )                              ");
-      expect(tokens[7][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[7][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[7][1].value).toBe("#");
-      expect(tokens[7][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[7][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[7][2].value).toBe(" End of group 'key'");
-      expect(tokens[7][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[7][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
       expect(tokens[8][0].value).toBe("    ");
-      expect(tokens[8][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[8][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[8][1].value).toBe("(");
-      expect(tokens[8][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
       expect(tokens[8][2].value).toBe("                              ");
-      expect(tokens[8][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[8][3].value).toBe("#");
-      expect(tokens[8][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[8][4].value).toBe(" Optional group: there may not be a value.");
-      expect(tokens[8][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
       expect(tokens[9][0].value).toBe("    ");
-      expect(tokens[9][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[9][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[9][1].value).toBe("\\s");
-      expect(tokens[9][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
+      expect(tokens[9][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
       expect(tokens[9][2].value).toBe("*");
-      expect(tokens[9][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[9][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
       expect(tokens[9][3].value).toBe("=");
-      expect(tokens[9][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[9][4].value).toBe("\\s");
-      expect(tokens[9][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
+      expect(tokens[9][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
       expect(tokens[9][5].value).toBe("*");
-      expect(tokens[9][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[9][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
       expect(tokens[9][6].value).toBe("                          ");
-      expect(tokens[9][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[9][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[9][7].value).toBe("#");
-      expect(tokens[9][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[9][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[9][8].value).toBe(" Equal Sign");
-      expect(tokens[9][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[9][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
       expect(tokens[10][0].value).toBe("    ");
-      expect(tokens[10][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[10][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[10][1].value).toBe("(");
-      expect(tokens[10][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[10][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"]);
       expect(tokens[10][2].value).toBe("?P<val>");
-      expect(tokens[10][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","entity.name.tag.named.group.regexp"]);
+      expect(tokens[10][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","entity.name.tag.named.group.regexp"]);
       expect(tokens[10][3].value).toBe("                         ");
-      expect(tokens[10][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[10][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[10][4].value).toBe("#");
-      expect(tokens[10][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[10][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[10][5].value).toBe(" Start of group 'val'");
-      expect(tokens[10][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[10][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
       expect(tokens[11][0].value).toBe("    \"");
-      expect(tokens[11][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[11][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[11][1].value).toBe("(?:");
-      expect(tokens[11][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[11][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp"]);
       expect(tokens[11][2].value).toBe("[");
-      expect(tokens[11][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[11][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
       expect(tokens[11][3].value).toBe("^");
-      expect(tokens[11][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","keyword.operator.negation.regexp"]);
+      expect(tokens[11][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","keyword.operator.negation.regexp"]);
       expect(tokens[11][4].value).toBe("\\\\");
-      expect(tokens[11][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.escape.regexp"]);
+      expect(tokens[11][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.escape.regexp"]);
       expect(tokens[11][5].value).toBe("\"");
-      expect(tokens[11][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[11][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.set.regexp"]);
       expect(tokens[11][6].value).toBe("]");
-      expect(tokens[11][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[11][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
       expect(tokens[11][7].value).toBe("|");
-      expect(tokens[11][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.disjunction.regexp"]);
+      expect(tokens[11][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.disjunction.regexp"]);
       expect(tokens[11][8].value).toBe("\\\\");
-      expect(tokens[11][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","constant.character.escape.regexp"]);
+      expect(tokens[11][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","constant.character.escape.regexp"]);
       expect(tokens[11][9].value).toBe(".");
-      expect(tokens[11][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.match.any.regexp"]);
+      expect(tokens[11][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.match.any.regexp"]);
       expect(tokens[11][10].value).toBe(")");
-      expect(tokens[11][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[11][10].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp"]);
       expect(tokens[11][11].value).toBe("*");
-      expect(tokens[11][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
+      expect(tokens[11][11].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
       expect(tokens[11][12].value).toBe("\"                  ");
-      expect(tokens[11][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[11][12].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[11][13].value).toBe("#");
-      expect(tokens[11][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[11][13].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[11][14].value).toBe(" Any doublequoted string");
-      expect(tokens[11][14].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[11][14].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
       expect(tokens[12][0].value).toBe("    ");
-      expect(tokens[12][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[12][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[12][1].value).toBe("|");
-      expect(tokens[12][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.disjunction.regexp"]);
+      expect(tokens[12][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.disjunction.regexp"]);
       expect(tokens[12][2].value).toBe("                                  ");
-      expect(tokens[12][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[12][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[12][3].value).toBe("#");
-      expect(tokens[12][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[12][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[12][4].value).toBe(" or");
-      expect(tokens[12][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[12][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
       expect(tokens[13][0].value).toBe("    ");
-      expect(tokens[13][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[13][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[13][1].value).toBe("\\w");
-      expect(tokens[13][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
       expect(tokens[13][2].value).toBe("{3}");
-      expect(tokens[13][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
+      expect(tokens[13][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
       expect(tokens[13][3].value).toBe(",");
-      expect(tokens[13][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[13][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[13][4].value).toBe("\\s");
-      expect(tokens[13][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
       expect(tokens[13][5].value).toBe("[");
-      expect(tokens[13][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[13][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
       expect(tokens[13][6].value).toBe("\\w");
-      expect(tokens[13][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
       expect(tokens[13][7].value).toBe("\\d");
-      expect(tokens[13][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
       expect(tokens[13][8].value).toBe("\\s");
-      expect(tokens[13][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
       expect(tokens[13][9].value).toBe("-");
-      expect(tokens[13][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[13][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.set.regexp"]);
       expect(tokens[13][10].value).toBe("]");
-      expect(tokens[13][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[13][10].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
       expect(tokens[13][11].value).toBe("{9,11}");
-      expect(tokens[13][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
+      expect(tokens[13][11].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
       expect(tokens[13][12].value).toBe("\\s");
-      expect(tokens[13][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][12].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
       expect(tokens[13][13].value).toBe("[");
-      expect(tokens[13][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[13][13].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
       expect(tokens[13][14].value).toBe("\\d");
-      expect(tokens[13][14].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][14].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","support.other.escape.special.regexp"]);
       expect(tokens[13][15].value).toBe(":");
-      expect(tokens[13][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.set.regexp"]);
+      expect(tokens[13][15].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.character.set.regexp"]);
       expect(tokens[13][16].value).toBe("]");
-      expect(tokens[13][16].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
+      expect(tokens[13][16].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
       expect(tokens[13][17].value).toBe("{8}");
-      expect(tokens[13][17].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
+      expect(tokens[13][17].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.quantifier.regexp"]);
       expect(tokens[13][18].value).toBe("\\s");
-      expect(tokens[13][18].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
+      expect(tokens[13][18].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","support.other.escape.special.regexp"]);
       expect(tokens[13][19].value).toBe("GMT  ");
-      expect(tokens[13][19].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[13][19].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[13][20].value).toBe("#");
-      expect(tokens[13][20].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[13][20].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[13][21].value).toBe(" Special case for \"expires\" attr");
-      expect(tokens[13][21].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[13][21].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
       expect(tokens[14][0].value).toBe("    ");
-      expect(tokens[14][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[14][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[14][1].value).toBe("|");
-      expect(tokens[14][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.disjunction.regexp"]);
+      expect(tokens[14][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","keyword.operator.disjunction.regexp"]);
       expect(tokens[14][2].value).toBe("                                  ");
-      expect(tokens[14][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[14][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[14][3].value).toBe("#");
-      expect(tokens[14][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[14][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[14][4].value).toBe(" or");
-      expect(tokens[14][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
+      expect(tokens[14][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","comment.line.number-sign.python"]);
       expect(tokens[15][0].value).toBe("    ");
-      expect(tokens[15][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
+      expect(tokens[15][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp"]);
       expect(tokens[15][1].value).toBe("[");
-      expect(tokens[15][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
+      expect(tokens[15][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","meta.named.regexp","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
       expect(tokens[15][2].value).toBe("\"\"\"");
-      expect(tokens[15][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[15][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
       expect(tokens[15][3].value).toBe(" ");
-      expect(tokens[15][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[15][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[15][4].value).toBe("+");
-      expect(tokens[15][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[15][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
       expect(tokens[15][5].value).toBe(" ");
-      expect(tokens[15][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[15][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[15][6].value).toBe("_LegalValueChars");
-      expect(tokens[15][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[15][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[15][7].value).toBe(" ");
-      expect(tokens[15][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[15][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[15][8].value).toBe("+");
-      expect(tokens[15][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[15][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.arithmetic.python"]);
       expect(tokens[15][9].value).toBe(" ");
-      expect(tokens[15][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[15][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[15][10].value).toBe("r");
-      expect(tokens[15][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
+      expect(tokens[15][10].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","storage.type.string.python"]);
       expect(tokens[15][11].value).toBe("\"\"\"");
-      expect(tokens[15][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[15][11].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.begin.python"]);
       expect(tokens[15][12].value).toBe("]");
-      expect(tokens[15][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[15][12].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[15][13].value).toBe("*");
-      expect(tokens[15][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[15][13].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
       expect(tokens[15][14].value).toBe("      ");
-      expect(tokens[15][14].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[15][14].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[15][15].value).toBe("#");
-      expect(tokens[15][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[15][15].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[15][16].value).toBe(" Any word or empty string");
-      expect(tokens[15][16].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[15][16].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
       expect(tokens[16][0].value).toBe("    )                                ");
-      expect(tokens[16][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[16][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[16][1].value).toBe("#");
-      expect(tokens[16][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[16][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[16][2].value).toBe(" End of group 'val'");
-      expect(tokens[16][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[16][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
       expect(tokens[17][0].value).toBe("    )");
-      expect(tokens[17][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[17][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[17][1].value).toBe("?");
-      expect(tokens[17][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[17][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
       expect(tokens[17][2].value).toBe("                             ");
-      expect(tokens[17][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[17][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[17][3].value).toBe("#");
-      expect(tokens[17][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[17][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[17][4].value).toBe(" End of optional value group");
-      expect(tokens[17][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[17][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
       expect(tokens[18][0].value).toBe("    ");
-      expect(tokens[18][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[18][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[18][1].value).toBe("\\s");
-      expect(tokens[18][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
+      expect(tokens[18][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
       expect(tokens[18][2].value).toBe("*");
-      expect(tokens[18][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[18][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
       expect(tokens[18][3].value).toBe("                            ");
-      expect(tokens[18][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[18][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[18][4].value).toBe("#");
-      expect(tokens[18][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[18][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[18][5].value).toBe(" Any number of spaces.");
-      expect(tokens[18][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[18][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
       expect(tokens[19][0].value).toBe("    ");
-      expect(tokens[19][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[19][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[19][1].value).toBe("(");
-      expect(tokens[19][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[19][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"]);
       expect(tokens[19][2].value).toBe("\\s");
-      expect(tokens[19][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
+      expect(tokens[19][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.escape.special.regexp"]);
       expect(tokens[19][3].value).toBe("+");
-      expect(tokens[19][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
+      expect(tokens[19][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.quantifier.regexp"]);
       expect(tokens[19][4].value).toBe("|");
-      expect(tokens[19][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.disjunction.regexp"]);
+      expect(tokens[19][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.disjunction.regexp"]);
       expect(tokens[19][5].value).toBe(";");
-      expect(tokens[19][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[19][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[19][6].value).toBe("|");
-      expect(tokens[19][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.disjunction.regexp"]);
+      expect(tokens[19][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","keyword.operator.disjunction.regexp"]);
       expect(tokens[19][7].value).toBe("$");
-      expect(tokens[19][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.match.end.regexp"]);
+      expect(tokens[19][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","support.other.match.end.regexp"]);
       expect(tokens[19][8].value).toBe(")");
-      expect(tokens[19][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"]);
+      expect(tokens[19][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"]);
       expect(tokens[19][9].value).toBe("                      ");
-      expect(tokens[19][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[19][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[19][10].value).toBe("#");
-      expect(tokens[19][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[19][10].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
       expect(tokens[19][11].value).toBe(" Ending either at space, semicolon, or EOS.");
-      expect(tokens[19][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
+      expect(tokens[19][11].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","comment.line.number-sign.python"]);
       expect(tokens[20][0].value).toBe("    ");
-      expect(tokens[20][0].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
+      expect(tokens[20][0].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python"]);
       expect(tokens[20][1].value).toBe("\"\"\"");
-      expect(tokens[20][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
+      expect(tokens[20][1].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
       expect(tokens[20][2].value).toBe(",");
-      expect(tokens[20][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[20][2].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
       expect(tokens[20][3].value).toBe(" ");
-      expect(tokens[20][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[20][3].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[20][4].value).toBe("re");
-      expect(tokens[20][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[20][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[20][5].value).toBe(".");
-      expect(tokens[20][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.period.python"]);
+      expect(tokens[20][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[20][6].value).toBe("ASCII");
-      expect(tokens[20][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.other.caps.python"]);
+      expect(tokens[20][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","meta.member.access.python","constant.other.caps.python"]);
       expect(tokens[20][7].value).toBe(")");
-      expect(tokens[20][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[20][7].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[20][8].value).toBe("                 ");
       expect(tokens[20][8].scopes).toEqual(["source.python"]);
       expect(tokens[20][9].value).toBe("#");
@@ -12512,9 +12512,9 @@ describe("Grammar Tests", function() {
       expect(tokens[3][0].value).toBe("foo");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
       expect(tokens[3][1].value).toBe(".");
-      expect(tokens[3][1].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("import");
-      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.control.import.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python","keyword.control.import.python"]);
       expect(tokens[4][0].value).toBe("");
       expect(tokens[4][0].scopes).toEqual(["source.python"]);
       expect(tokens[5][0].value).toBe("raise");
@@ -13275,11 +13275,11 @@ describe("Grammar Tests", function() {
       expect(tokens[2][9].value).toBe("\"");
       expect(tokens[2][9].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[2][10].value).toBe(".");
-      expect(tokens[2][10].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][11].value).toBe("format");
-      expect(tokens[2][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[2][11].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[2][12].value).toBe("(");
-      expect(tokens[2][12].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][12].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
     });
 
   it("test/strings/bytes1.py", 
@@ -13856,19 +13856,19 @@ describe("Grammar Tests", function() {
       expect(tokens[0][17].value).toBe("\"");
       expect(tokens[0][17].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
       expect(tokens[0][18].value).toBe(".");
-      expect(tokens[0][18].scopes).toEqual(["source.python","punctuation.separator.period.python"]);
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][19].value).toBe("format");
-      expect(tokens[0][19].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.generic.python"]);
       expect(tokens[0][20].value).toBe("(");
-      expect(tokens[0][20].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][21].value).toBe("fo");
-      expect(tokens[0][21].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
       expect(tokens[0][22].value).toBe("=");
-      expect(tokens[0][22].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
       expect(tokens[0][23].value).toBe("1");
-      expect(tokens[0][23].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
       expect(tokens[0][24].value).toBe(")");
-      expect(tokens[0][24].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][24].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
     });
 
   it("test/strings/format3.py", 
diff --git a/test/builtins/builtins3.py b/test/builtins/builtins3.py
index 02ccb5af..17972344 100644
--- a/test/builtins/builtins3.py
+++ b/test/builtins/builtins3.py
@@ -60,127 +60,127 @@
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 ]             : punctuation.definition.list.end.python, source.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__bases__     : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__bases__     : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__class__     : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__class__     : meta.member.access.python, source.python, support.variable.magic.python
 assert        : keyword.control.flow.python, source.python
               : source.python
 __debug__     : source.python, support.variable.magic.python
 __builtins__  : source.python, support.variable.magic.python
 __builtins__  : source.python, support.variable.magic.python
-.             : punctuation.separator.period.python, source.python
-len           : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+len           : meta.member.access.python, source.python
 print         : meta.function-call.python, source.python, support.function.builtin.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 __builtins__  : meta.function-call.arguments.python, meta.function-call.python, source.python, support.variable.magic.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__dict__      : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__dict__      : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__doc__       : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__doc__       : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__file__      : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__file__      : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__members__   : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__members__   : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__metaclass__ : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__metaclass__ : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__methods__   : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__methods__   : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__module__    : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__module__    : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__mro__       : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__mro__       : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__name__      : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__name__      : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__slots__     : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__slots__     : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__subclasses__ : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__subclasses__ : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__version__   : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__version__   : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__weakref__   : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__weakref__   : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__qualname__  : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__qualname__  : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__code__      : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__code__      : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__wrapped__   : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__wrapped__   : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__signature__ : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__signature__ : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__defaults__  : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__defaults__  : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__func__      : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__func__      : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__self__      : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__self__      : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__kwdefaults__ : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__kwdefaults__ : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__matmul__    : source.python, support.function.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__matmul__    : meta.member.access.python, source.python, support.function.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__imatmul__   : source.python, support.function.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__imatmul__   : meta.member.access.python, source.python, support.function.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__rmatmul__   : source.python, support.function.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__rmatmul__   : meta.member.access.python, source.python, support.function.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__annotations__ : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__annotations__ : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__init_subclass__ : source.python, support.function.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__init_subclass__ : meta.member.access.python, source.python, support.function.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__set_name__  : source.python, support.function.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__set_name__  : meta.member.access.python, source.python, support.function.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__fspath__    : source.python, support.function.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__fspath__    : meta.member.access.python, source.python, support.function.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__classcell__ : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__classcell__ : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__bytes__     : source.python, support.function.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__bytes__     : meta.member.access.python, source.python, support.function.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__spec__      : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__spec__      : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__path__      : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__path__      : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__prepare__   : source.python, support.function.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__prepare__   : meta.member.access.python, source.python, support.function.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__package__   : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__package__   : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__traceback__ : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__traceback__ : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-__notspecial__ : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__notspecial__ : meta.member.access.python, source.python
diff --git a/test/builtins/builtins4.py b/test/builtins/builtins4.py
index b8f3401b..ac82589a 100644
--- a/test/builtins/builtins4.py
+++ b/test/builtins/builtins4.py
@@ -7,21 +7,22 @@
 
 
 
+
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-int           : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+int           : meta.member.access.python, source.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-sum           : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+sum           : meta.member.access.python, source.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-super         : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+super         : meta.member.access.python, source.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-unicode       : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+unicode       : meta.member.access.python, source.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-foo           : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+foo           : meta.member.access.python, source.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-Exception     : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+Exception     : meta.member.access.python, source.python
diff --git a/test/builtins/builtins5.py b/test/builtins/builtins5.py
index 674df37f..af3db3e5 100644
--- a/test/builtins/builtins5.py
+++ b/test/builtins/builtins5.py
@@ -7,20 +7,21 @@
 
 
 
+
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
-True          : keyword.illegal.name.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
+True          : keyword.illegal.name.python, meta.member.access.python, source.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
-\             : punctuation.separator.continuation.line.python, source.python
-              : source.python
-              : source.python
-True          : keyword.illegal.name.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
+\             : meta.member.access.python, punctuation.separator.continuation.line.python, source.python
+              : meta.member.access.python, source.python
+              : meta.member.access.python, source.python
+True          : keyword.illegal.name.python, meta.member.access.python, source.python
 True          : constant.language.python, source.python
 some          : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
-              : source.python
-True          : keyword.illegal.name.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
+              : meta.member.access.python, source.python
+True          : keyword.illegal.name.python, meta.member.access.python, source.python
diff --git a/test/calls/call3.py b/test/calls/call3.py
index 3e5bca3d..3eb5ff59 100644
--- a/test/calls/call3.py
+++ b/test/calls/call3.py
@@ -4,17 +4,18 @@
 
 
 
+
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-class         : keyword.control.flow.python, meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-a             : meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+class         : keyword.control.flow.python, meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+a             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-and           : keyword.control.flow.python, meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+and           : keyword.control.flow.python, meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-if            : keyword.control.flow.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+if            : keyword.control.flow.python, meta.member.access.python, source.python
diff --git a/test/calls/call4.py b/test/calls/call4.py
index a2976601..9cfce7af 100644
--- a/test/calls/call4.py
+++ b/test/calls/call4.py
@@ -4,9 +4,10 @@
 
 
 
+
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-1             : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+1             : meta.member.access.python, source.python
 foo           : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 bar           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
@@ -19,13 +20,13 @@
 sam           : meta.function-call.arguments.python, meta.function-call.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-None          : keyword.illegal.name.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+None          : keyword.illegal.name.python, meta.member.access.python, source.python
               : source.python
 and           : keyword.operator.logical.python, source.python
               : source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-None          : keyword.illegal.name.python, source.python
-.             : punctuation.separator.period.python, source.python
-baz           : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+None          : keyword.illegal.name.python, meta.member.access.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+baz           : meta.member.access.python, source.python
diff --git a/test/calls/call7.py b/test/calls/call7.py
index b0b00f05..97cf7ee9 100644
--- a/test/calls/call7.py
+++ b/test/calls/call7.py
@@ -7,43 +7,44 @@
 
 
 
+
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-__class__     : meta.function-call.python, source.python, support.variable.magic.python
-              : meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__class__     : meta.function-call.python, meta.member.access.python, source.python, support.variable.magic.python
+              : meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+foo           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+bar           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-__class__     : meta.function-call.python, source.python, support.variable.magic.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__class__     : meta.function-call.python, meta.member.access.python, source.python, support.variable.magic.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+foo           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+bar           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-__add__       : meta.function-call.python, source.python, support.function.magic.python
-              : meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__add__       : meta.function-call.python, meta.member.access.python, source.python, support.function.magic.python
+              : meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+foo           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+bar           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-__add__       : meta.function-call.python, source.python, support.function.magic.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__add__       : meta.function-call.python, meta.member.access.python, source.python, support.function.magic.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+foo           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+bar           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
               : source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-__class__     : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__class__     : meta.member.access.python, source.python, support.variable.magic.python
               : source.python
 1             : constant.numeric.dec.python, source.python
diff --git a/test/calls/call8.py b/test/calls/call8.py
index 471a64d3..0b78f3d3 100644
--- a/test/calls/call8.py
+++ b/test/calls/call8.py
@@ -5,41 +5,42 @@
 
 
 
+
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
-__class__     : meta.function-call.python, source.python, support.variable.magic.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
+__class__     : meta.function-call.python, meta.member.access.python, source.python, support.variable.magic.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+foo           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+bar           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
-__class__     : meta.function-call.python, source.python, support.variable.magic.python
-              : meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
+__class__     : meta.function-call.python, meta.member.access.python, source.python, support.variable.magic.python
+              : meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+foo           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+bar           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
-__add__       : meta.function-call.python, source.python, support.function.magic.python
-              : meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
+__add__       : meta.function-call.python, meta.member.access.python, source.python, support.function.magic.python
+              : meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+foo           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+bar           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
-__add__       : meta.function-call.python, source.python, support.function.magic.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-bar           : meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
+__add__       : meta.function-call.python, meta.member.access.python, source.python, support.function.magic.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+foo           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+bar           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/calls/print1.py b/test/calls/print1.py
index c5f3e7f7..8ce2b03f 100644
--- a/test/calls/print1.py
+++ b/test/calls/print1.py
@@ -11,6 +11,7 @@
 
 
 
+
 print         : source.python, support.function.builtin.python
               : source.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
@@ -55,8 +56,8 @@
               : source.python
 >>            : keyword.operator.bitwise.python, source.python
 sys           : source.python
-.             : punctuation.separator.period.python, source.python
-stderr        : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+stderr        : meta.member.access.python, source.python
 ,             : punctuation.separator.element.python, source.python
               : source.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
@@ -72,8 +73,8 @@
 file          : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
 =             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 sys           : meta.function-call.arguments.python, meta.function-call.python, source.python
-.             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.period.python, source.python
-stderr        : meta.function-call.arguments.python, meta.function-call.python, source.python
+.             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.separator.period.python, source.python
+stderr        : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 print         : meta.function-call.python, source.python, support.function.builtin.python
               : meta.function-call.python, source.python
diff --git a/test/classes/class11.py b/test/classes/class11.py
index bad00706..4995c536 100644
--- a/test/classes/class11.py
+++ b/test/classes/class11.py
@@ -10,6 +10,7 @@ def __init__(self, a, b=1):
 
 
 
+
 class         : meta.class.python, source.python, storage.type.class.python
               : meta.class.python, source.python
 F             : entity.name.type.class.python, meta.class.python, source.python
@@ -32,16 +33,16 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 :             : meta.function.python, punctuation.section.function.begin.python, source.python
               : source.python
 self          : source.python, variable.language.special.self.python
-.             : punctuation.separator.period.python, source.python
-a             : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+a             : meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 a             : source.python
               : source.python
 self          : source.python, variable.language.special.self.python
-.             : punctuation.separator.period.python, source.python
-b             : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+b             : meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
@@ -57,18 +58,18 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
               : source.python
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-self          : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+self          : meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 1             : constant.numeric.dec.python, source.python
               : source.python
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-self          : source.python
-.             : punctuation.separator.period.python, source.python
-bar           : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+self          : meta.member.access.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+bar           : meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
diff --git a/test/classes/class12.py b/test/classes/class12.py
index e0e7fb7d..2d34fc81 100644
--- a/test/classes/class12.py
+++ b/test/classes/class12.py
@@ -12,6 +12,7 @@ def meth(cls, a, b=1):
 
 
 
+
 class         : meta.class.python, source.python, storage.type.class.python
               : meta.class.python, source.python
 F             : entity.name.type.class.python, meta.class.python, source.python
@@ -37,16 +38,16 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 :             : meta.function.python, punctuation.section.function.begin.python, source.python
               : source.python
 cls           : source.python, variable.language.special.cls.python
-.             : punctuation.separator.period.python, source.python
-a             : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+a             : meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 a             : source.python
               : source.python
 cls           : source.python, variable.language.special.cls.python
-.             : punctuation.separator.period.python, source.python
-b             : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+b             : meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
@@ -68,18 +69,18 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 1             : constant.numeric.dec.python, source.python
               : source.python
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-cls           : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+cls           : meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 1             : constant.numeric.dec.python, source.python
               : source.python
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-cls           : source.python
-.             : punctuation.separator.period.python, source.python
-__name__      : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+cls           : meta.member.access.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__name__      : meta.member.access.python, source.python, support.variable.magic.python
               : source.python
 cls           : meta.item-access.python, source.python, variable.language.special.cls.python
 [             : meta.item-access.python, punctuation.definition.arguments.begin.python, source.python
diff --git a/test/classes/class14.py b/test/classes/class14.py
index 706969f9..45455895 100644
--- a/test/classes/class14.py
+++ b/test/classes/class14.py
@@ -3,26 +3,27 @@ class F(f.Exception, f.type, Exception, Exception.a, b=Exception):
 
 
 
+
 class         : meta.class.python, source.python, storage.type.class.python
               : meta.class.python, source.python
 F             : entity.name.type.class.python, meta.class.python, source.python
 (             : meta.class.inheritance.python, meta.class.python, punctuation.definition.inheritance.begin.python, source.python
 f             : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
-.             : meta.class.inheritance.python, meta.class.python, punctuation.separator.period.python, source.python
-Exception     : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
+.             : meta.class.inheritance.python, meta.class.python, meta.member.access.python, punctuation.separator.period.python, source.python
+Exception     : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, meta.member.access.python, source.python
 ,             : meta.class.inheritance.python, meta.class.python, punctuation.separator.inheritance.python, source.python
               : meta.class.inheritance.python, meta.class.python, source.python
 f             : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
-.             : meta.class.inheritance.python, meta.class.python, punctuation.separator.period.python, source.python
-type          : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
+.             : meta.class.inheritance.python, meta.class.python, meta.member.access.python, punctuation.separator.period.python, source.python
+type          : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, meta.member.access.python, source.python
 ,             : meta.class.inheritance.python, meta.class.python, punctuation.separator.inheritance.python, source.python
               : meta.class.inheritance.python, meta.class.python, source.python
 Exception     : meta.class.inheritance.python, meta.class.python, source.python, support.type.exception.python
 ,             : meta.class.inheritance.python, meta.class.python, punctuation.separator.inheritance.python, source.python
               : meta.class.inheritance.python, meta.class.python, source.python
 Exception     : meta.class.inheritance.python, meta.class.python, source.python, support.type.exception.python
-.             : meta.class.inheritance.python, meta.class.python, punctuation.separator.period.python, source.python
-a             : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
+.             : meta.class.inheritance.python, meta.class.python, meta.member.access.python, punctuation.separator.period.python, source.python
+a             : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, meta.member.access.python, source.python
 ,             : meta.class.inheritance.python, meta.class.python, punctuation.separator.inheritance.python, source.python
               : meta.class.inheritance.python, meta.class.python, source.python
 b             : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python, variable.parameter.class.python
diff --git a/test/classes/class2.py b/test/classes/class2.py
index 32b5a2dc..1f15e252 100644
--- a/test/classes/class2.py
+++ b/test/classes/class2.py
@@ -5,6 +5,7 @@ class Spam(Foo.Bar, Bar.name={'very': 'odd'}):
 
 
 
+
 @             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 dec           : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
@@ -14,13 +15,13 @@ class         : meta.class.python, source.python, storage.type.class.python
 Spam          : entity.name.type.class.python, meta.class.python, source.python
 (             : meta.class.inheritance.python, meta.class.python, punctuation.definition.inheritance.begin.python, source.python
 Foo           : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
-.             : meta.class.inheritance.python, meta.class.python, punctuation.separator.period.python, source.python
-Bar           : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
+.             : meta.class.inheritance.python, meta.class.python, meta.member.access.python, punctuation.separator.period.python, source.python
+Bar           : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, meta.member.access.python, source.python
 ,             : meta.class.inheritance.python, meta.class.python, punctuation.separator.inheritance.python, source.python
               : meta.class.inheritance.python, meta.class.python, source.python
 Bar           : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
-.             : meta.class.inheritance.python, meta.class.python, punctuation.separator.period.python, source.python
-name          : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, source.python
+.             : meta.class.inheritance.python, meta.class.python, meta.member.access.python, punctuation.separator.period.python, source.python
+name          : entity.other.inherited-class.python, meta.class.inheritance.python, meta.class.python, meta.member.access.python, source.python
 =             : keyword.operator.assignment.python, meta.class.inheritance.python, meta.class.python, source.python
 {             : meta.class.inheritance.python, meta.class.python, punctuation.definition.dict.begin.python, source.python
 '             : meta.class.inheritance.python, meta.class.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
diff --git a/test/classes/super1.py b/test/classes/super1.py
index 1840ed9b..709205c4 100644
--- a/test/classes/super1.py
+++ b/test/classes/super1.py
@@ -30,39 +30,39 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 super         : meta.function-call.python, source.python, support.type.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
-.             : punctuation.separator.period.python, source.python
-__init__      : meta.function-call.python, source.python, support.function.magic.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__init__      : meta.function-call.python, meta.member.access.python, source.python, support.function.magic.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+foo           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
               : source.python
 super         : meta.function-call.python, source.python, support.type.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
-__init__      : meta.function-call.python, source.python, support.function.magic.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
+__init__      : meta.function-call.python, meta.member.access.python, source.python, support.function.magic.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+foo           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
               : source.python
 super         : meta.function-call.python, source.python, support.type.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
-\             : punctuation.separator.continuation.line.python, source.python
-              : source.python
-__init__      : meta.function-call.python, source.python, support.function.magic.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-foo           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
+\             : meta.member.access.python, punctuation.separator.continuation.line.python, source.python
+              : meta.member.access.python, source.python
+__init__      : meta.function-call.python, meta.member.access.python, source.python, support.function.magic.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+foo           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
               : source.python
 __init__      : meta.function-call.python, source.python, support.function.magic.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
@@ -73,13 +73,13 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : source.python
               : source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-__init__      : meta.function-call.python, source.python, support.function.magic.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-bar           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__init__      : meta.function-call.python, meta.member.access.python, source.python, support.function.magic.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+bar           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
               : source.python
 __init__      : meta.function-call.python, source.python, support.function.magic.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
diff --git a/test/expressions/const1.py b/test/expressions/const1.py
index e59a19be..384f93be 100644
--- a/test/expressions/const1.py
+++ b/test/expressions/const1.py
@@ -3,6 +3,7 @@
 
 
 
+
 QQQQ          : constant.other.caps.python, source.python
               : source.python
 QQQQ_123      : constant.other.caps.python, source.python
@@ -12,27 +13,27 @@
 PROTOCOL_v2   : constant.other.caps.python, source.python
               : source.python
 QQQ           : constant.other.caps.python, source.python
-.             : punctuation.separator.period.python, source.python
-bar           : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+bar           : meta.member.access.python, source.python
               : source.python
 baz           : source.python
-.             : punctuation.separator.period.python, source.python
-AA_a          : constant.other.caps.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+AA_a          : constant.other.caps.python, meta.member.access.python, source.python
               : source.python
 _AAA          : constant.other.caps.python, source.python
               : source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-_AAA          : constant.other.caps.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+_AAA          : constant.other.caps.python, meta.member.access.python, source.python
 QQQq          : source.python
               : source.python
 QQQq123       : source.python
               : source.python
 self          : source.python, variable.language.special.self.python
-.             : punctuation.separator.period.python, source.python
-FOOO          : meta.function-call.generic.python, meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+FOOO          : meta.function-call.generic.python, meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
               : source.python
 _             : source.python
               : source.python
diff --git a/test/expressions/expr10.py b/test/expressions/expr10.py
index 501fb475..df5f1165 100644
--- a/test/expressions/expr10.py
+++ b/test/expressions/expr10.py
@@ -5,6 +5,7 @@
 
 
 
+
 a             : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
@@ -32,5 +33,5 @@
 ...           : constant.other.ellipsis.python, source.python
 )             : punctuation.parenthesis.end.python, source.python
 ...           : constant.other.ellipsis.python, source.python
-.             : punctuation.separator.period.python, source.python
-__class__     : source.python, support.variable.magic.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__class__     : meta.member.access.python, source.python, support.variable.magic.python
diff --git a/test/expressions/expr11.py b/test/expressions/expr11.py
index 142ff621..754112c8 100644
--- a/test/expressions/expr11.py
+++ b/test/expressions/expr11.py
@@ -2,15 +2,16 @@
 
 
 
+
 a             : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 self          : source.python, variable.language.special.self.python
-.             : punctuation.separator.period.python, source.python
-some_list     : meta.item-access.python, source.python
-[             : meta.item-access.python, punctuation.definition.arguments.begin.python, source.python
-1             : constant.numeric.dec.python, meta.item-access.arguments.python, meta.item-access.python, source.python
-:             : meta.item-access.arguments.python, meta.item-access.python, punctuation.separator.slice.python, source.python
-2             : constant.numeric.dec.python, meta.item-access.arguments.python, meta.item-access.python, source.python
-]             : meta.item-access.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+some_list     : meta.item-access.python, meta.member.access.python, source.python
+[             : meta.item-access.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+1             : constant.numeric.dec.python, meta.item-access.arguments.python, meta.item-access.python, meta.member.access.python, source.python
+:             : meta.item-access.arguments.python, meta.item-access.python, meta.member.access.python, punctuation.separator.slice.python, source.python
+2             : constant.numeric.dec.python, meta.item-access.arguments.python, meta.item-access.python, meta.member.access.python, source.python
+]             : meta.item-access.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/expressions/expr15.py b/test/expressions/expr15.py
index 2815cdae..0685ff23 100644
--- a/test/expressions/expr15.py
+++ b/test/expressions/expr15.py
@@ -2,6 +2,7 @@
 
 
 
+
 foofrom       : source.python
-.             : punctuation.separator.period.python, source.python
-something     : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+something     : meta.member.access.python, source.python
diff --git a/test/expressions/expr18.py b/test/expressions/expr18.py
index 8326520f..3ef0ad22 100644
--- a/test/expressions/expr18.py
+++ b/test/expressions/expr18.py
@@ -3,9 +3,10 @@
 
 
 
+
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-Exception     : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+Exception     : meta.member.access.python, source.python
 Exception     : source.python, support.type.exception.python
-.             : punctuation.separator.period.python, source.python
-a             : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+a             : meta.member.access.python, source.python
diff --git a/test/expressions/expr19.py b/test/expressions/expr19.py
index 45dd0e8e..4a4a3a5b 100644
--- a/test/expressions/expr19.py
+++ b/test/expressions/expr19.py
@@ -11,40 +11,41 @@
 
 
 
+
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
 foo           : comment.line.number-sign.python, source.python
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
 foo           : comment.line.number-sign.python, source.python
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
-\             : punctuation.separator.continuation.line.python, source.python
-              : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
+\             : meta.member.access.python, punctuation.separator.continuation.line.python, source.python
+              : meta.member.access.python, source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
 foo           : comment.line.number-sign.python, source.python
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 bar           : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
 '             : punctuation.definition.string.begin.python, source.python, string.quoted.docstring.single.python
 bar           : source.python, string.quoted.docstring.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.docstring.single.python
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-              : source.python
-\             : punctuation.separator.continuation.line.python, source.python
-              : source.python
-'             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
-bar           : source.python, string.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+              : meta.member.access.python, source.python
+\             : meta.member.access.python, punctuation.separator.continuation.line.python, source.python
+              : meta.member.access.python, source.python
+'             : meta.member.access.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+bar           : meta.member.access.python, source.python, string.quoted.single.python
+'             : meta.member.access.python, punctuation.definition.string.end.python, source.python, string.quoted.single.python
diff --git a/test/expressions/expr7.py b/test/expressions/expr7.py
index 936af9e8..8bfa1704 100644
--- a/test/expressions/expr7.py
+++ b/test/expressions/expr7.py
@@ -2,18 +2,19 @@
 
 
 
+
 a             : source.python
-.             : punctuation.separator.period.python, source.python
-True          : keyword.illegal.name.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+True          : keyword.illegal.name.python, meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 b             : source.python
-.             : punctuation.separator.period.python, source.python
-False         : keyword.illegal.name.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+False         : keyword.illegal.name.python, meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 d             : source.python
-.             : punctuation.separator.period.python, source.python
-None          : keyword.illegal.name.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+None          : keyword.illegal.name.python, meta.member.access.python, source.python
diff --git a/test/fstrings/comment4.py b/test/fstrings/comment4.py
index f070cdd0..66943523 100644
--- a/test/fstrings/comment4.py
+++ b/test/fstrings/comment4.py
@@ -4,36 +4,36 @@
 
 
 self          : source.python, variable.language.special.self.python
-.             : punctuation.separator.period.python, source.python
-assertEqual   : meta.function-call.generic.python, meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-f             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
-'             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
-{             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-10            : constant.numeric.dec.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-:             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.format.python
-#             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.format.python
-{             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-3             : constant.numeric.dec.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-              : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-!=            : keyword.operator.comparison.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-              : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-{             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.dict.begin.python, source.python
-4             : constant.numeric.dec.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-:             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.dict.python, source.python
-5             : constant.numeric.dec.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-}             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.dict.end.python, source.python
-              : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-and           : keyword.operator.logical.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-              : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-width         : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-}             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-x             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.format.python
-}             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-'             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
-,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python
-'             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
-       0xa    : meta.function-call.arguments.python, meta.function-call.python, source.python, string.quoted.single.python
-'             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.quoted.single.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+assertEqual   : meta.function-call.generic.python, meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+f             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
+'             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+10            : constant.numeric.dec.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+:             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, storage.type.format.python
+#             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, storage.type.format.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+3             : constant.numeric.dec.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+              : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+!=            : keyword.operator.comparison.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+              : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+{             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.dict.begin.python, source.python
+4             : constant.numeric.dec.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+:             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.separator.dict.python, source.python
+5             : constant.numeric.dec.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+}             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.dict.end.python, source.python
+              : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+and           : keyword.operator.logical.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+              : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+width         : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+x             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, storage.type.format.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+'             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
+,             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+'             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+       0xa    : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.quoted.single.python
+'             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.string.end.python, source.python, string.quoted.single.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/fstrings/simple2.py b/test/fstrings/simple2.py
index 48ce0dcd..e4e1ff37 100644
--- a/test/fstrings/simple2.py
+++ b/test/fstrings/simple2.py
@@ -2,6 +2,7 @@
 
 
 
+
 a             : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
@@ -22,8 +23,8 @@
  normal       : meta.fstring.python, source.python, string.interpolated.python, string.quoted.single.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 fo            : meta.fstring.python, source.python
-.             : meta.fstring.python, punctuation.separator.period.python, source.python
-__add__       : meta.fstring.python, source.python, support.function.magic.python
+.             : meta.fstring.python, meta.member.access.python, punctuation.separator.period.python, source.python
+__add__       : meta.fstring.python, meta.member.access.python, source.python, support.function.magic.python
 !s            : meta.fstring.python, source.python, storage.type.format.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 "             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
diff --git a/test/illegals/illegal1.py b/test/illegals/illegal1.py
index 6010bc4f..5ee9654d 100644
--- a/test/illegals/illegal1.py
+++ b/test/illegals/illegal1.py
@@ -9,6 +9,7 @@ def f(): pass
 
 
 
+
 ->            : invalid.illegal.annotation.python, source.python
 def           : meta.function.python, source.python, storage.type.function.python
               : meta.function.python, source.python
@@ -28,13 +29,13 @@ def           : meta.function.python, source.python, storage.type.function.pytho
 .class        : source.python, string.quoted.single.python
 '             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 )             : punctuation.parenthesis.end.python, source.python
-.             : punctuation.separator.period.python, source.python
-fuuuu         : meta.function-call.generic.python, meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-baz           : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+fuuuu         : meta.function-call.generic.python, meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+baz           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
  we recover just fine : comment.line.number-sign.python, source.python
 b             : source.python
diff --git a/test/regexp/python8.py b/test/regexp/python8.py
index f0babc73..ba72a7be 100644
--- a/test/regexp/python8.py
+++ b/test/regexp/python8.py
@@ -22,6 +22,7 @@
 
 
 
+
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
  And now something fun! : comment.line.number-sign.python, source.python
               : source.python
@@ -30,166 +31,166 @@
 =             : keyword.operator.assignment.python, source.python
               : source.python
 re            : source.python
-.             : punctuation.separator.period.python, source.python
-compile       : meta.function-call.generic.python, meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-r             : meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.regexp.quoted.multi.python
-"""           : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-(?x)          : meta.function-call.arguments.python, meta.function-call.python, source.python, storage.modifier.flag.regexp, string.regexp.quoted.multi.python
-                            : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- This is a verbose pattern : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-\s            : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-                             : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- Optional whitespace at start of cookie : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-(             : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.parenthesis.named.begin.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
-?P<key>       : entity.name.tag.named.group.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-                        : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- Start of group 'key' : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-[             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.character.set.begin.regexp, source.python, string.regexp.quoted.multi.python
-"""           : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python
-+             : keyword.operator.arithmetic.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python
-_LegalKeyChars : meta.function-call.arguments.python, meta.function-call.python, source.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python
-+             : keyword.operator.arithmetic.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python
-r             : meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.regexp.quoted.multi.python
-"""           : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.regexp.quoted.multi.python
-]             : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-+?            : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- Any word of at least one letter : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-    )                               : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- End of group 'key' : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-(             : meta.function-call.arguments.python, meta.function-call.python, punctuation.parenthesis.begin.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
-                               : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- Optional group: there may not be a value. : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-\s            : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-=             : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-\s            : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-                           : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- Equal Sign   : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-(             : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.parenthesis.named.begin.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
-?P<val>       : entity.name.tag.named.group.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-                          : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- Start of group 'val' : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-    "         : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-(?:           : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.parenthesis.non-capturing.begin.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
-[             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.character.set.begin.regexp, source.python, string.regexp.quoted.multi.python
-^             : keyword.operator.negation.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-\\            : constant.character.escape.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-"             : constant.character.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-]             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.character.set.end.regexp, source.python, string.regexp.quoted.multi.python
-|             : keyword.operator.disjunction.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-\\            : constant.character.escape.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-.             : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.match.any.regexp
-)             : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.parenthesis.non-capturing.end.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
-*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-"                   : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- Any doublequoted string : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-|             : keyword.operator.disjunction.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-                                   : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- or           : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-\w            : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-{3}           : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-,             : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-\s            : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-[             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.character.set.begin.regexp, source.python, string.regexp.quoted.multi.python
-\w            : meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-\d            : meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-\s            : meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
--             : constant.character.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-]             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.character.set.end.regexp, source.python, string.regexp.quoted.multi.python
-{9,11}        : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-\s            : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-[             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.character.set.begin.regexp, source.python, string.regexp.quoted.multi.python
-\d            : meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-:             : constant.character.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-]             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.character.set.end.regexp, source.python, string.regexp.quoted.multi.python
-{8}           : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-\s            : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-GMT           : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- Special case for "expires" attr : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-|             : keyword.operator.disjunction.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-                                   : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- or           : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
-[             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.named.regexp, punctuation.character.set.begin.regexp, source.python, string.regexp.quoted.multi.python
-"""           : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python
-+             : keyword.operator.arithmetic.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python
-_LegalValueChars : meta.function-call.arguments.python, meta.function-call.python, source.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python
-+             : keyword.operator.arithmetic.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python
-r             : meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.regexp.quoted.multi.python
-"""           : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.regexp.quoted.multi.python
-]             : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- Any word or empty string : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-    )                                 : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- End of group 'val' : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-    )         : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-?             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-                              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- End of optional value group : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-\s            : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-                             : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- Any number of spaces. : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-(             : meta.function-call.arguments.python, meta.function-call.python, punctuation.parenthesis.begin.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
-\s            : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
-+             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-|             : keyword.operator.disjunction.regexp, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-;             : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-|             : keyword.operator.disjunction.regexp, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-$             : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python, support.other.match.end.regexp
-)             : meta.function-call.arguments.python, meta.function-call.python, punctuation.parenthesis.end.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
-                       : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
- Ending either at space, semicolon, or EOS. : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python, string.regexp.quoted.multi.python
-"""           : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.regexp.quoted.multi.python
-,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
-              : meta.function-call.arguments.python, meta.function-call.python, source.python
-re            : meta.function-call.arguments.python, meta.function-call.python, source.python
-.             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.period.python, source.python
-ASCII         : constant.other.caps.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+compile       : meta.function-call.generic.python, meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+r             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, storage.type.string.python, string.regexp.quoted.multi.python
+"""           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.string.begin.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+(?x)          : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, storage.modifier.flag.regexp, string.regexp.quoted.multi.python
+                            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ This is a verbose pattern : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+\s            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+                             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ Optional whitespace at start of cookie : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+(             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.parenthesis.named.begin.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
+?P<key>       : entity.name.tag.named.group.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+                        : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ Start of group 'key' : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+[             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.character.set.begin.regexp, source.python, string.regexp.quoted.multi.python
+"""           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.string.end.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
++             : keyword.operator.arithmetic.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+_LegalKeyChars : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
++             : keyword.operator.arithmetic.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+r             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, storage.type.string.python, string.regexp.quoted.multi.python
+"""           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.string.begin.python, source.python, string.regexp.quoted.multi.python
+]             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
++?            : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ Any word of at least one letter : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+    )                               : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ End of group 'key' : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+(             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.parenthesis.begin.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
+                               : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ Optional group: there may not be a value. : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+\s            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+=             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+\s            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+                           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ Equal Sign   : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+(             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.parenthesis.named.begin.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
+?P<val>       : entity.name.tag.named.group.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+                          : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ Start of group 'val' : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+    "         : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+(?:           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.parenthesis.non-capturing.begin.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
+[             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.character.set.begin.regexp, source.python, string.regexp.quoted.multi.python
+^             : keyword.operator.negation.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+\\            : constant.character.escape.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+"             : constant.character.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+]             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.character.set.end.regexp, source.python, string.regexp.quoted.multi.python
+|             : keyword.operator.disjunction.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+\\            : constant.character.escape.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+.             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.match.any.regexp
+)             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.parenthesis.non-capturing.end.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
+*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+"                   : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ Any doublequoted string : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+|             : keyword.operator.disjunction.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+                                   : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ or           : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+\w            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+{3}           : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+,             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+\s            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+[             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.character.set.begin.regexp, source.python, string.regexp.quoted.multi.python
+\w            : meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+\d            : meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+\s            : meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+-             : constant.character.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+]             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.character.set.end.regexp, source.python, string.regexp.quoted.multi.python
+{9,11}        : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+\s            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+[             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.character.set.begin.regexp, source.python, string.regexp.quoted.multi.python
+\d            : meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+:             : constant.character.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+]             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.character.set.end.regexp, source.python, string.regexp.quoted.multi.python
+{8}           : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+\s            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+GMT           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ Special case for "expires" attr : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+|             : keyword.operator.disjunction.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+                                   : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ or           : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, source.python, string.regexp.quoted.multi.python
+[             : constant.other.set.regexp, meta.character.set.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, meta.named.regexp, punctuation.character.set.begin.regexp, source.python, string.regexp.quoted.multi.python
+"""           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.string.end.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
++             : keyword.operator.arithmetic.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+_LegalValueChars : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
++             : keyword.operator.arithmetic.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+r             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, storage.type.string.python, string.regexp.quoted.multi.python
+"""           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.string.begin.python, source.python, string.regexp.quoted.multi.python
+]             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ Any word or empty string : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+    )                                 : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ End of group 'val' : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+    )         : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+?             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+                              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ End of optional value group : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+\s            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
+*             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+                             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ Any number of spaces. : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+(             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.parenthesis.begin.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
+\s            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python, support.other.escape.special.regexp
++             : keyword.operator.quantifier.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+|             : keyword.operator.disjunction.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+;             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+|             : keyword.operator.disjunction.regexp, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+$             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python, support.other.match.end.regexp
+)             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.parenthesis.end.regexp, source.python, string.regexp.quoted.multi.python, support.other.parenthesis.regexp
+                       : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+#             : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.comment.python, source.python, string.regexp.quoted.multi.python
+ Ending either at space, semicolon, or EOS. : comment.line.number-sign.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, string.regexp.quoted.multi.python
+"""           : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.definition.string.end.python, source.python, string.regexp.quoted.multi.python
+,             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+re            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+.             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.separator.period.python, source.python
+ASCII         : constant.other.caps.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
                   : source.python
 #             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
  May be removed if safe. : comment.line.number-sign.python, source.python
diff --git a/test/statements/import5.py b/test/statements/import5.py
index 01c57822..6050a777 100644
--- a/test/statements/import5.py
+++ b/test/statements/import5.py
@@ -10,6 +10,7 @@ def bar():
 
 
 
+
 from          : keyword.control.import.python, source.python
 .             : punctuation.separator.period.python, source.python
 foo           : source.python
@@ -24,8 +25,8 @@ def bar():
 a             : source.python
               : source.python
 foo           : source.python
-.             : punctuation.separator.period.python, source.python
-import        : keyword.control.import.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+import        : keyword.control.import.python, meta.member.access.python, source.python
               : source.python
 raise         : keyword.control.flow.python, source.python
               : source.python
diff --git a/test/strings/bug2.py b/test/strings/bug2.py
index 0ba2bf8f..3f4622e8 100644
--- a/test/strings/bug2.py
+++ b/test/strings/bug2.py
@@ -30,6 +30,6 @@
  -- ./**/*.proto >  : source.python, string.quoted.single.python
 {OUTPUT}      : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
-.             : punctuation.separator.period.python, source.python
-format        : meta.function-call.generic.python, meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+format        : meta.function-call.generic.python, meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
diff --git a/test/strings/format2.py b/test/strings/format2.py
index 86227776..d6079535 100644
--- a/test/strings/format2.py
+++ b/test/strings/format2.py
@@ -2,6 +2,7 @@
 
 
 
+
 a             : source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
@@ -20,10 +21,10 @@
 !s            : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, storage.type.format.python, string.quoted.single.python
 }             : constant.character.format.placeholder.other.python, meta.format.brace.python, source.python, string.quoted.single.python
 "             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
-.             : punctuation.separator.period.python, source.python
-format        : meta.function-call.generic.python, meta.function-call.python, source.python
-(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
-fo            : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
-=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+format        : meta.function-call.generic.python, meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+fo            : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python

From 076e2bb99d458068f0b83b0576372995242fcb6d Mon Sep 17 00:00:00 2001
From: Yury Selivanov <yury@edgedb.com>
Date: Thu, 17 Oct 2019 17:53:44 -0400
Subject: [PATCH 52/65] Bump syntaxdev dep

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 92b1a2ec..e859e0b7 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,7 @@
   },
   "devDependencies": {
     "oniguruma": "^7.0.0",
-    "syntaxdev": "^0.1.0"
+    "syntaxdev": "^0.1.3"
   },
   "dependencies": {}
 }

From 9d40c7165cdd4d72129dafa29dced3e17c5b83bf Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@edgedb.com>
Date: Thu, 17 Oct 2019 18:33:31 -0400
Subject: [PATCH 53/65] Add an `update-test` make target.

The `update-test` make target will automatically update the output of
any test that failed. This kind of bulk update is intended to be used
when the changes to scopes affect a large number of files. Of course, the
actual updated tests should still be reviewed for correctness.
---
 Makefile | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Makefile b/Makefile
index 85c19a17..21b1edbf 100644
--- a/Makefile
+++ b/Makefile
@@ -15,6 +15,11 @@ ci-test: release
 	] ; \
 		then echo "Error: package.version != git.tag" && exit 1 ; fi
 
+update-test:
+#	Run tests and overwrite the output
+	./node_modules/.bin/syntaxdev test --tests test/**/*.py --syntax grammars/src/MagicPython.syntax.yaml --overwrite-tests
+	./node_modules/.bin/syntaxdev test --tests test/**/*.re --syntax grammars/src/MagicRegExp.syntax.yaml --overwrite-tests
+
 test: ci-test
 	atom -t test/atom-spec
 

From c9b3409deb69acec31bbf7913830e93a046b30cc Mon Sep 17 00:00:00 2001
From: Anthony Sottile <asottile@umich.edu>
Date: Sat, 15 Feb 2020 17:06:09 -0800
Subject: [PATCH 54/65] Regenerate tmLanguage files using `make` (#196)

---
 grammars/MagicPython.tmLanguage | 2 +-
 grammars/MagicRegExp.tmLanguage | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index ba24d9d1..6b243795 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -1,7 +1,7 @@
-<!-- AUTOGENERATED FROM grammars/src/MagicPython.syntax.yaml -->
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
+  <!-- AUTOGENERATED FROM grammars/src/MagicPython.syntax.yaml -->
   <dict>
     <key>name</key>
     <string>MagicPython</string>
diff --git a/grammars/MagicRegExp.tmLanguage b/grammars/MagicRegExp.tmLanguage
index 3d19e058..3ddacc70 100644
--- a/grammars/MagicRegExp.tmLanguage
+++ b/grammars/MagicRegExp.tmLanguage
@@ -1,7 +1,7 @@
-<!-- AUTOGENERATED FROM grammars/src/MagicRegExp.syntax.yaml -->
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
+  <!-- AUTOGENERATED FROM grammars/src/MagicRegExp.syntax.yaml -->
   <dict>
     <key>name</key>
     <string>MagicRegExp</string>

From 0b09c1fca238d22e15ac5712d03f9bf6da626f9c Mon Sep 17 00:00:00 2001
From: Michael Wilkinson <goi42@users.noreply.github.com>
Date: Mon, 30 Mar 2020 20:45:22 -0400
Subject: [PATCH 55/65] Add snakemake (#203)

---
 grammars/MagicPython.cson            | 1 +
 grammars/MagicPython.tmLanguage      | 1 +
 grammars/src/MagicPython.syntax.yaml | 2 +-
 package.json                         | 6 +++++-
 4 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 33f23dad..0529d39d 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -17,6 +17,7 @@ fileTypes: [
   "wsgi"
   "kv"
   "Snakefile"
+  "smk"
   "tac"
 ]
 first_line_match: "^#![ \\t]*/.*\\bpython[\\d\\.]*\\b"
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 6b243795..8f3b643c 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -24,6 +24,7 @@
       <string>wsgi</string>
       <string>kv</string>
       <string>Snakefile</string>
+      <string>smk</string>
       <string>tac</string>
     </array>
     <key>first_line_match</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 7dbec777..97209a62 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -4,7 +4,7 @@ scopeName: source.python
 # NOTE: remember to update package.json with VSCode file types.
 fileTypes: [py, py3, rpy, pyw, cpy, pyi,
             SConstruct, Sconstruct, sconstruct, SConscript,
-            gyp, gypi, wsgi, kv, Snakefile, tac]
+            gyp, gypi, wsgi, kv, Snakefile, smk, tac]
 first_line_match: ^#![ \t]*/.*\bpython[\d\.]*\b
 firstLineMatch: ^#![ \t]*/.*\bpython[\d\.]*\b
 uuid: 742deb57-6e38-4192-bed6-410746efd85d
diff --git a/package.json b/package.json
index e859e0b7..a974bd74 100644
--- a/package.json
+++ b/package.json
@@ -55,7 +55,11 @@
           ".SConscript",
           ".gyp",
           ".gypi",
-          ".wsgi"
+          ".wsgi",
+          ".kv",
+          "Snakefile",
+          ".smk",
+          ".tac"
         ]
       }
     ],

From dd48b8f87748ffb743466c12095ea66075f84c4c Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@edgedb.com>
Date: Wed, 23 Oct 2019 12:09:16 -0400
Subject: [PATCH 56/65] Add some more specific scopes for member access.

Add `meta.attribute.python` to mark otherwise non-special attributes.
Add `meta.indexed-name.python` to mark the name of the object being
indexed.

In combination with `meta.member.access.python` the above scopes can
help highlight member access that is no otherwise using a builtin or
some other special case. For highlighting method names in method calls
the combination of `meta.member.access.python` and
`meta.function-call.generic.python` could be used.

Fixes #188.
---
 grammars/MagicPython.cson            | 12 ++++++
 grammars/MagicPython.tmLanguage      | 17 ++++++++
 grammars/src/MagicPython.syntax.yaml | 11 ++++-
 misc/scopes                          |  2 +
 test/atom-spec/python-spec.js        | 62 ++++++++++++++--------------
 test/builtins/builtins3.py           |  4 +-
 test/builtins/builtins4.py           | 12 +++---
 test/calls/call1.py                  |  3 +-
 test/calls/call4.py                  |  2 +-
 test/calls/print1.py                 |  4 +-
 test/classes/class11.py              | 10 ++---
 test/classes/class12.py              |  8 ++--
 test/expressions/const1.py           |  2 +-
 test/expressions/expr11.py           |  2 +-
 test/expressions/expr15.py           |  2 +-
 test/expressions/expr18.py           |  4 +-
 test/fstrings/nested1.py             |  2 +-
 test/functions/decl2.py              |  4 +-
 test/functions/decorators6.py        |  4 +-
 test/statements/annotation1.py       |  3 +-
 test/strings/bytes2.py               |  3 +-
 21 files changed, 110 insertions(+), 63 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 0529d39d..0cf28d5e 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -431,6 +431,9 @@ repository:
       {
         include: "#member-access-base"
       }
+      {
+        include: "#member-access-attribute"
+      }
     ]
   "member-access-base":
     patterns: [
@@ -453,6 +456,14 @@ repository:
         include: "#item-access"
       }
     ]
+  "member-access-attribute":
+    comment: "Highlight attribute access in otherwise non-specialized cases."
+    name: "meta.attribute.python"
+    match: '''
+      (?x)
+        \\b ([[:alpha:]_]\\w*) \\b
+      
+    '''
   "special-names":
     name: "constant.other.caps.python"
     match: '''
@@ -1488,6 +1499,7 @@ repository:
         include: "#special-names"
       }
       {
+        name: "meta.indexed-name.python"
         match: '''
           (?x)
             \\b ([[:alpha:]_]\\w*) \\b
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 8f3b643c..81d6e2d7 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -647,6 +647,10 @@ it's probably control flow like:
             <key>include</key>
             <string>#member-access-base</string>
           </dict>
+          <dict>
+            <key>include</key>
+            <string>#member-access-attribute</string>
+          </dict>
         </array>
       </dict>
       <key>member-access-base</key>
@@ -679,6 +683,17 @@ it's probably control flow like:
           </dict>
         </array>
       </dict>
+      <key>member-access-attribute</key>
+      <dict>
+        <key>comment</key>
+        <string>Highlight attribute access in otherwise non-specialized cases.</string>
+        <key>name</key>
+        <string>meta.attribute.python</string>
+        <key>match</key>
+        <string>(?x)
+  \b ([[:alpha:]_]\w*) \b
+</string>
+      </dict>
       <key>special-names</key>
       <dict>
         <key>name</key>
@@ -2340,6 +2355,8 @@ it's probably control flow like:
             <string>#special-names</string>
           </dict>
           <dict>
+            <key>name</key>
+            <string>meta.indexed-name.python</string>
             <key>match</key>
             <string>(?x)
   \b ([[:alpha:]_]\w*) \b
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 97209a62..c39cc8d2 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -449,6 +449,7 @@ repository:
     patterns:
       - include: '#function-call'
       - include: '#member-access-base'
+      - include: '#member-access-attribute'
 
   member-access-base:
     patterns:
@@ -459,6 +460,13 @@ repository:
       - include: '#line-continuation'
       - include: '#item-access'
 
+  member-access-attribute:
+    comment: Highlight attribute access in otherwise non-specialized cases.
+    name: meta.attribute.python
+    match: |
+      (?x)
+        \b ([[:alpha:]_]\w*) \b
+
   special-names:
     name: constant.other.caps.python
     match: |
@@ -1142,7 +1150,8 @@ repository:
       - include: '#special-variables'
       - include: '#builtin-functions'
       - include: '#special-names'
-      - match: |
+      - name: meta.indexed-name.python
+        match: |
           (?x)
             \b ([[:alpha:]_]\w*) \b
 
diff --git a/misc/scopes b/misc/scopes
index 17a74a4a..12785af1 100644
--- a/misc/scopes
+++ b/misc/scopes
@@ -60,6 +60,7 @@ keyword.operator.python
 keyword.operator.quantifier.regexp
 keyword.operator.unpacking.arguments.python
 keyword.operator.unpacking.parameter.python
+meta.attribute.python
 meta.backreference.named.regexp
 meta.backreference.regexp
 meta.character.set.regexp
@@ -73,6 +74,7 @@ meta.function-call.python
 meta.function.decorator.python
 meta.function.parameters.python
 meta.function.python
+meta.indexed-name.python
 meta.item-access.python
 meta.lambda-function.python
 meta.member.access.python
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index d1c7466b..2d052ff2 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -188,7 +188,7 @@ describe("Grammar Tests", function() {
       expect(tokens[5][1].value).toBe(".");
       expect(tokens[5][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[5][2].value).toBe("len");
-      expect(tokens[5][2].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[6][0].value).toBe("print");
       expect(tokens[6][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
       expect(tokens[6][1].value).toBe("(");
@@ -412,7 +412,7 @@ describe("Grammar Tests", function() {
       expect(tokens[42][1].value).toBe(".");
       expect(tokens[42][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[42][2].value).toBe("__notspecial__");
-      expect(tokens[42][2].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[42][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
     });
 
   it("test/builtins/builtins4.py", 
@@ -423,37 +423,37 @@ describe("Grammar Tests", function() {
       expect(tokens[0][1].value).toBe(".");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("int");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[1][0].value).toBe("some");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe(".");
       expect(tokens[1][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("sum");
-      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[2][0].value).toBe("some");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe(".");
       expect(tokens[2][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][2].value).toBe("super");
-      expect(tokens[2][2].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[3][0].value).toBe("some");
       expect(tokens[3][0].scopes).toEqual(["source.python"]);
       expect(tokens[3][1].value).toBe(".");
       expect(tokens[3][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][2].value).toBe("unicode");
-      expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[4][0].value).toBe("some");
       expect(tokens[4][0].scopes).toEqual(["source.python"]);
       expect(tokens[4][1].value).toBe(".");
       expect(tokens[4][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[4][2].value).toBe("foo");
-      expect(tokens[4][2].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[5][0].value).toBe("some");
       expect(tokens[5][0].scopes).toEqual(["source.python"]);
       expect(tokens[5][1].value).toBe(".");
       expect(tokens[5][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[5][2].value).toBe("Exception");
-      expect(tokens[5][2].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[5][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
     });
 
   it("test/builtins/builtins5.py", 
@@ -545,7 +545,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][7].value).toBe(" ");
       expect(tokens[0][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
       expect(tokens[0][8].value).toBe("c");
-      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.item-access.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.item-access.python","meta.indexed-name.python"]);
       expect(tokens[0][9].value).toBe("[");
       expect(tokens[0][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][10].value).toBe("1");
@@ -753,7 +753,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][9].value).toBe(".");
       expect(tokens[2][9].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][10].value).toBe("baz");
-      expect(tokens[2][10].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
     });
 
   it("test/calls/call5.py", 
@@ -1111,7 +1111,7 @@ describe("Grammar Tests", function() {
       expect(tokens[6][4].value).toBe(".");
       expect(tokens[6][4].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[6][5].value).toBe("stderr");
-      expect(tokens[6][5].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[6][6].value).toBe(",");
       expect(tokens[6][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
       expect(tokens[6][7].value).toBe(" ");
@@ -1145,7 +1145,7 @@ describe("Grammar Tests", function() {
       expect(tokens[7][10].value).toBe(".");
       expect(tokens[7][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[7][11].value).toBe("stderr");
-      expect(tokens[7][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.member.access.python"]);
+      expect(tokens[7][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[7][12].value).toBe(")");
       expect(tokens[7][12].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
       expect(tokens[8][0].value).toBe("print");
@@ -1316,7 +1316,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][2].value).toBe(".");
       expect(tokens[2][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[2][3].value).toBe("a");
-      expect(tokens[2][3].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[2][4].value).toBe(" ");
       expect(tokens[2][4].scopes).toEqual(["source.python"]);
       expect(tokens[2][5].value).toBe("=");
@@ -1332,7 +1332,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][2].value).toBe(".");
       expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][3].value).toBe("b");
-      expect(tokens[3][3].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[3][4].value).toBe(" ");
       expect(tokens[3][4].scopes).toEqual(["source.python"]);
       expect(tokens[3][5].value).toBe("=");
@@ -1366,7 +1366,7 @@ describe("Grammar Tests", function() {
       expect(tokens[6][2].value).toBe(".");
       expect(tokens[6][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[6][3].value).toBe("self");
-      expect(tokens[6][3].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[6][4].value).toBe(" ");
       expect(tokens[6][4].scopes).toEqual(["source.python"]);
       expect(tokens[6][5].value).toBe("=");
@@ -1382,11 +1382,11 @@ describe("Grammar Tests", function() {
       expect(tokens[7][2].value).toBe(".");
       expect(tokens[7][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[7][3].value).toBe("self");
-      expect(tokens[7][3].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[7][3].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[7][4].value).toBe(".");
       expect(tokens[7][4].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[7][5].value).toBe("bar");
-      expect(tokens[7][5].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[7][5].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[7][6].value).toBe(" ");
       expect(tokens[7][6].scopes).toEqual(["source.python"]);
       expect(tokens[7][7].value).toBe("=");
@@ -1463,7 +1463,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][2].value).toBe(".");
       expect(tokens[3][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[3][3].value).toBe("a");
-      expect(tokens[3][3].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[3][4].value).toBe(" ");
       expect(tokens[3][4].scopes).toEqual(["source.python"]);
       expect(tokens[3][5].value).toBe("=");
@@ -1479,7 +1479,7 @@ describe("Grammar Tests", function() {
       expect(tokens[4][2].value).toBe(".");
       expect(tokens[4][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[4][3].value).toBe("b");
-      expect(tokens[4][3].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[4][4].value).toBe(" ");
       expect(tokens[4][4].scopes).toEqual(["source.python"]);
       expect(tokens[4][5].value).toBe("=");
@@ -1525,7 +1525,7 @@ describe("Grammar Tests", function() {
       expect(tokens[8][2].value).toBe(".");
       expect(tokens[8][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[8][3].value).toBe("cls");
-      expect(tokens[8][3].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[8][4].value).toBe(" ");
       expect(tokens[8][4].scopes).toEqual(["source.python"]);
       expect(tokens[8][5].value).toBe("=");
@@ -1541,7 +1541,7 @@ describe("Grammar Tests", function() {
       expect(tokens[9][2].value).toBe(".");
       expect(tokens[9][2].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[9][3].value).toBe("cls");
-      expect(tokens[9][3].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[9][3].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[9][4].value).toBe(".");
       expect(tokens[9][4].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[9][5].value).toBe("__name__");
@@ -5071,7 +5071,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][9].value).toBe(".");
       expect(tokens[0][9].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][10].value).toBe("bar");
-      expect(tokens[0][10].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[0][11].value).toBe(" ");
       expect(tokens[0][11].scopes).toEqual(["source.python"]);
       expect(tokens[0][12].value).toBe("baz");
@@ -5394,7 +5394,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][5].value).toBe(".");
       expect(tokens[0][5].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][6].value).toBe("some_list");
-      expect(tokens[0][6].scopes).toEqual(["source.python","meta.member.access.python","meta.item-access.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.member.access.python","meta.item-access.python","meta.indexed-name.python"]);
       expect(tokens[0][7].value).toBe("[");
       expect(tokens[0][7].scopes).toEqual(["source.python","meta.member.access.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][8].value).toBe("1");
@@ -5470,7 +5470,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][1].value).toBe(".");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("something");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
     });
 
   it("test/expressions/expr16.py", 
@@ -5541,13 +5541,13 @@ describe("Grammar Tests", function() {
       expect(tokens[0][1].value).toBe(".");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[0][2].value).toBe("Exception");
-      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
       expect(tokens[1][0].value).toBe("Exception");
       expect(tokens[1][0].scopes).toEqual(["source.python","support.type.exception.python"]);
       expect(tokens[1][1].value).toBe(".");
       expect(tokens[1][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
       expect(tokens[1][2].value).toBe("a");
-      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
     });
 
   it("test/expressions/expr19.py", 
@@ -6537,7 +6537,7 @@ describe("Grammar Tests", function() {
       expect(tokens[4][2].value).toBe(" ");
       expect(tokens[4][2].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python"]);
       expect(tokens[4][3].value).toBe("bar");
-      expect(tokens[4][3].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.item-access.python"]);
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.item-access.python","meta.indexed-name.python"]);
       expect(tokens[4][4].value).toBe("[");
       expect(tokens[4][4].scopes).toEqual(["source.python","meta.fstring.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[4][5].value).toBe("\"");
@@ -8458,7 +8458,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][11].value).toBe(" ");
       expect(tokens[0][11].scopes).toEqual(["source.python","meta.function.python"]);
       expect(tokens[0][12].value).toBe("qqq");
-      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function.python","meta.item-access.python"]);
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function.python","meta.item-access.python","meta.indexed-name.python"]);
       expect(tokens[0][13].value).toBe("[");
       expect(tokens[0][13].scopes).toEqual(["source.python","meta.function.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][14].value).toBe("None");
@@ -9363,7 +9363,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][0].value).toBe("       ");
       expect(tokens[2][0].scopes).toEqual(["source.python"]);
       expect(tokens[2][1].value).toBe("baz");
-      expect(tokens[2][1].scopes).toEqual(["source.python","meta.item-access.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.item-access.python","meta.indexed-name.python"]);
       expect(tokens[2][2].value).toBe("[");
       expect(tokens[2][2].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[2][3].value).toBe("1");
@@ -12045,7 +12045,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][2].value).toBe(" ");
       expect(tokens[1][2].scopes).toEqual(["source.python"]);
       expect(tokens[1][3].value).toBe("List");
-      expect(tokens[1][3].scopes).toEqual(["source.python","meta.item-access.python"]);
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.item-access.python","meta.indexed-name.python"]);
       expect(tokens[1][4].value).toBe("[");
       expect(tokens[1][4].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[1][5].value).toBe("int");
@@ -13321,7 +13321,7 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("a[1] = b'''\nmultiline 'binary' string \\\n\n    \\xf1 \\u1234aaaa \\U1234aaaa\n\n    \\N{BLACK SPADE SUIT}\n'''")
       expect(tokens[0][0].value).toBe("a");
-      expect(tokens[0][0].scopes).toEqual(["source.python","meta.item-access.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.item-access.python","meta.indexed-name.python"]);
       expect(tokens[0][1].value).toBe("[");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][2].value).toBe("1");
diff --git a/test/builtins/builtins3.py b/test/builtins/builtins3.py
index 17972344..181eacd1 100644
--- a/test/builtins/builtins3.py
+++ b/test/builtins/builtins3.py
@@ -71,7 +71,7 @@
 __builtins__  : source.python, support.variable.magic.python
 __builtins__  : source.python, support.variable.magic.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-len           : meta.member.access.python, source.python
+len           : meta.attribute.python, meta.member.access.python, source.python
 print         : meta.function-call.python, source.python, support.function.builtin.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 __builtins__  : meta.function-call.arguments.python, meta.function-call.python, source.python, support.variable.magic.python
@@ -183,4 +183,4 @@
 __traceback__ : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-__notspecial__ : meta.member.access.python, source.python
+__notspecial__ : meta.attribute.python, meta.member.access.python, source.python
diff --git a/test/builtins/builtins4.py b/test/builtins/builtins4.py
index ac82589a..d126c0bf 100644
--- a/test/builtins/builtins4.py
+++ b/test/builtins/builtins4.py
@@ -10,19 +10,19 @@
 
 some          : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-int           : meta.member.access.python, source.python
+int           : meta.attribute.python, meta.member.access.python, source.python
 some          : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-sum           : meta.member.access.python, source.python
+sum           : meta.attribute.python, meta.member.access.python, source.python
 some          : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-super         : meta.member.access.python, source.python
+super         : meta.attribute.python, meta.member.access.python, source.python
 some          : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-unicode       : meta.member.access.python, source.python
+unicode       : meta.attribute.python, meta.member.access.python, source.python
 some          : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-foo           : meta.member.access.python, source.python
+foo           : meta.attribute.python, meta.member.access.python, source.python
 some          : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-Exception     : meta.member.access.python, source.python
+Exception     : meta.attribute.python, meta.member.access.python, source.python
diff --git a/test/calls/call1.py b/test/calls/call1.py
index aab3f9f7..86f32acb 100644
--- a/test/calls/call1.py
+++ b/test/calls/call1.py
@@ -2,6 +2,7 @@
 
 
 
+
 some_call     : meta.function-call.generic.python, meta.function-call.python, source.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 A             : meta.function-call.arguments.python, meta.function-call.python, source.python
@@ -10,7 +11,7 @@
 b             : meta.function-call.arguments.python, meta.function-call.python, source.python
 ,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
               : meta.function-call.arguments.python, meta.function-call.python, source.python
-c             : meta.function-call.arguments.python, meta.function-call.python, meta.item-access.python, source.python
+c             : meta.function-call.arguments.python, meta.function-call.python, meta.indexed-name.python, meta.item-access.python, source.python
 [             : meta.function-call.arguments.python, meta.function-call.python, meta.item-access.python, punctuation.definition.arguments.begin.python, source.python
 1             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, meta.item-access.arguments.python, meta.item-access.python, source.python
 ]             : meta.function-call.arguments.python, meta.function-call.python, meta.item-access.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/calls/call4.py b/test/calls/call4.py
index 9cfce7af..6da33186 100644
--- a/test/calls/call4.py
+++ b/test/calls/call4.py
@@ -29,4 +29,4 @@
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
 None          : keyword.illegal.name.python, meta.member.access.python, source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-baz           : meta.member.access.python, source.python
+baz           : meta.attribute.python, meta.member.access.python, source.python
diff --git a/test/calls/print1.py b/test/calls/print1.py
index 8ce2b03f..9339060e 100644
--- a/test/calls/print1.py
+++ b/test/calls/print1.py
@@ -57,7 +57,7 @@
 >>            : keyword.operator.bitwise.python, source.python
 sys           : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-stderr        : meta.member.access.python, source.python
+stderr        : meta.attribute.python, meta.member.access.python, source.python
 ,             : punctuation.separator.element.python, source.python
               : source.python
 "             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
@@ -74,7 +74,7 @@
 =             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
 sys           : meta.function-call.arguments.python, meta.function-call.python, source.python
 .             : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, punctuation.separator.period.python, source.python
-stderr        : meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+stderr        : meta.attribute.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
 print         : meta.function-call.python, source.python, support.function.builtin.python
               : meta.function-call.python, source.python
diff --git a/test/classes/class11.py b/test/classes/class11.py
index 4995c536..4cb0b927 100644
--- a/test/classes/class11.py
+++ b/test/classes/class11.py
@@ -34,7 +34,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : source.python
 self          : source.python, variable.language.special.self.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-a             : meta.member.access.python, source.python
+a             : meta.attribute.python, meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
@@ -42,7 +42,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : source.python
 self          : source.python, variable.language.special.self.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-b             : meta.member.access.python, source.python
+b             : meta.attribute.python, meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
@@ -59,7 +59,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : source.python
 a             : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-self          : meta.member.access.python, source.python
+self          : meta.attribute.python, meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
@@ -67,9 +67,9 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : source.python
 a             : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-self          : meta.member.access.python, source.python
+self          : meta.attribute.python, meta.member.access.python, source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-bar           : meta.member.access.python, source.python
+bar           : meta.attribute.python, meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
diff --git a/test/classes/class12.py b/test/classes/class12.py
index 2d34fc81..838a1bb2 100644
--- a/test/classes/class12.py
+++ b/test/classes/class12.py
@@ -39,7 +39,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : source.python
 cls           : source.python, variable.language.special.cls.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-a             : meta.member.access.python, source.python
+a             : meta.attribute.python, meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
@@ -47,7 +47,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : source.python
 cls           : source.python, variable.language.special.cls.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-b             : meta.member.access.python, source.python
+b             : meta.attribute.python, meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
@@ -70,7 +70,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : source.python
 a             : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-cls           : meta.member.access.python, source.python
+cls           : meta.attribute.python, meta.member.access.python, source.python
               : source.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
@@ -78,7 +78,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : source.python
 a             : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-cls           : meta.member.access.python, source.python
+cls           : meta.attribute.python, meta.member.access.python, source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
 __name__      : meta.member.access.python, source.python, support.variable.magic.python
               : source.python
diff --git a/test/expressions/const1.py b/test/expressions/const1.py
index 384f93be..5288d71a 100644
--- a/test/expressions/const1.py
+++ b/test/expressions/const1.py
@@ -14,7 +14,7 @@
               : source.python
 QQQ           : constant.other.caps.python, source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-bar           : meta.member.access.python, source.python
+bar           : meta.attribute.python, meta.member.access.python, source.python
               : source.python
 baz           : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
diff --git a/test/expressions/expr11.py b/test/expressions/expr11.py
index 754112c8..de8e348c 100644
--- a/test/expressions/expr11.py
+++ b/test/expressions/expr11.py
@@ -9,7 +9,7 @@
               : source.python
 self          : source.python, variable.language.special.self.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-some_list     : meta.item-access.python, meta.member.access.python, source.python
+some_list     : meta.indexed-name.python, meta.item-access.python, meta.member.access.python, source.python
 [             : meta.item-access.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
 1             : constant.numeric.dec.python, meta.item-access.arguments.python, meta.item-access.python, meta.member.access.python, source.python
 :             : meta.item-access.arguments.python, meta.item-access.python, meta.member.access.python, punctuation.separator.slice.python, source.python
diff --git a/test/expressions/expr15.py b/test/expressions/expr15.py
index 0685ff23..4038218a 100644
--- a/test/expressions/expr15.py
+++ b/test/expressions/expr15.py
@@ -5,4 +5,4 @@
 
 foofrom       : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-something     : meta.member.access.python, source.python
+something     : meta.attribute.python, meta.member.access.python, source.python
diff --git a/test/expressions/expr18.py b/test/expressions/expr18.py
index 3ef0ad22..6e9413bf 100644
--- a/test/expressions/expr18.py
+++ b/test/expressions/expr18.py
@@ -6,7 +6,7 @@
 
 a             : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-Exception     : meta.member.access.python, source.python
+Exception     : meta.attribute.python, meta.member.access.python, source.python
 Exception     : source.python, support.type.exception.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
-a             : meta.member.access.python, source.python
+a             : meta.attribute.python, meta.member.access.python, source.python
diff --git a/test/fstrings/nested1.py b/test/fstrings/nested1.py
index d7d1c8bf..91f15907 100644
--- a/test/fstrings/nested1.py
+++ b/test/fstrings/nested1.py
@@ -26,7 +26,7 @@
               : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.interpolated.python, string.quoted.multi.python
 {             : constant.character.format.placeholder.other.python, meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
               : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python
-bar           : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.item-access.python, source.python
+bar           : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.indexed-name.python, meta.item-access.python, source.python
 [             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.item-access.python, punctuation.definition.arguments.begin.python, source.python
 "             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.item-access.arguments.python, meta.item-access.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
 q             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, meta.item-access.arguments.python, meta.item-access.python, source.python, string.quoted.single.python
diff --git a/test/functions/decl2.py b/test/functions/decl2.py
index 7da74fcb..f858ea26 100644
--- a/test/functions/decl2.py
+++ b/test/functions/decl2.py
@@ -2,6 +2,8 @@ def result_annot(lambda, lambda=) -> qqq[None]:
     pass
 
 
+
+
 def           : meta.function.python, source.python, storage.type.function.python
               : meta.function.python, source.python
 result_annot  : entity.name.function.python, meta.function.python, source.python
@@ -14,7 +16,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : meta.function.python, source.python
 ->            : meta.function.python, punctuation.separator.annotation.result.python, source.python
               : meta.function.python, source.python
-qqq           : meta.function.python, meta.item-access.python, source.python
+qqq           : meta.function.python, meta.indexed-name.python, meta.item-access.python, source.python
 [             : meta.function.python, meta.item-access.python, punctuation.definition.arguments.begin.python, source.python
 None          : constant.language.python, meta.function.python, meta.item-access.arguments.python, meta.item-access.python, source.python
 ]             : meta.function.python, meta.item-access.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/functions/decorators6.py b/test/functions/decorators6.py
index 8a167cad..5c9b4289 100644
--- a/test/functions/decorators6.py
+++ b/test/functions/decorators6.py
@@ -6,6 +6,8 @@
 def foo(): pass
 
 
+
+
 @             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.definition.decorator.python, source.python
 a             : entity.name.function.decorator.python, meta.function.decorator.python, source.python
 .             : entity.name.function.decorator.python, meta.function.decorator.python, punctuation.separator.period.python, source.python
@@ -29,7 +31,7 @@ def foo(): pass
 )             : meta.function.decorator.python, punctuation.definition.arguments.end.python, source.python
 . \           : invalid.illegal.decorator.python, meta.function.decorator.python, source.python
               : source.python
-baz           : meta.item-access.python, source.python
+baz           : meta.indexed-name.python, meta.item-access.python, source.python
 [             : meta.item-access.python, punctuation.definition.arguments.begin.python, source.python
 1             : constant.numeric.dec.python, meta.item-access.arguments.python, meta.item-access.python, source.python
 :             : meta.item-access.arguments.python, meta.item-access.python, punctuation.separator.slice.python, source.python
diff --git a/test/statements/annotation1.py b/test/statements/annotation1.py
index a72bafc6..332cd26a 100644
--- a/test/statements/annotation1.py
+++ b/test/statements/annotation1.py
@@ -3,6 +3,7 @@
 
 
 
+
 some_number   : source.python
 :             : punctuation.separator.colon.python, source.python
               : source.python
@@ -13,7 +14,7 @@
 some_list     : source.python
 :             : punctuation.separator.colon.python, source.python
               : source.python
-List          : meta.item-access.python, source.python
+List          : meta.indexed-name.python, meta.item-access.python, source.python
 [             : meta.item-access.python, punctuation.definition.arguments.begin.python, source.python
 int           : meta.item-access.arguments.python, meta.item-access.python, source.python, support.type.python
 ]             : meta.item-access.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/strings/bytes2.py b/test/strings/bytes2.py
index 22df557e..7aefd973 100644
--- a/test/strings/bytes2.py
+++ b/test/strings/bytes2.py
@@ -8,7 +8,8 @@
 
 
 
-a             : meta.item-access.python, source.python
+
+a             : meta.indexed-name.python, meta.item-access.python, source.python
 [             : meta.item-access.python, punctuation.definition.arguments.begin.python, source.python
 1             : constant.numeric.dec.python, meta.item-access.arguments.python, meta.item-access.python, source.python
 ]             : meta.item-access.python, punctuation.definition.arguments.end.python, source.python

From 72ccccbf68bb3e4e858e50386edaa0c55f637d8e Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@edgedb.com>
Date: Fri, 1 May 2020 07:43:27 -0400
Subject: [PATCH 57/65] Improve detection of call signature and kwargs.

Correctly identify calls of the form "foo[123](bar=2)" to highlight the
contents of the parentheses as call arguments.

Issue: #197
---
 grammars/MagicPython.cson            | 26 ++++++++++
 grammars/MagicPython.tmLanguage      | 36 ++++++++++++++
 grammars/src/MagicPython.syntax.yaml | 17 +++++++
 test/atom-spec/python-spec.js        | 71 ++++++++++++++++++++++++++++
 test/calls/call11.py                 | 44 +++++++++++++++++
 5 files changed, 194 insertions(+)
 create mode 100644 test/calls/call11.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 0cf28d5e..c3a2a5f5 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -343,6 +343,9 @@ repository:
       {
         include: "#list"
       }
+      {
+        include: "#odd-function-call"
+      }
       {
         include: "#round-braces"
       }
@@ -513,6 +516,28 @@ repository:
         include: "#expression"
       }
     ]
+  "odd-function-call":
+    comment: '''
+      A bit obscured function call where there may have been an
+      arbitrary number of other operations to get the function.
+      E.g. "arr[idx](args)"
+      
+    '''
+    begin: '''
+      (?x)
+        (?<= \\] | \\) ) \\s*
+        (?=\\()
+      
+    '''
+    end: "(\\))"
+    endCaptures:
+      "1":
+        name: "punctuation.definition.arguments.end.python"
+    patterns: [
+      {
+        include: "#function-arguments"
+      }
+    ]
   "round-braces":
     begin: "\\("
     end: "\\)"
@@ -1627,6 +1652,7 @@ repository:
     ]
   "function-call":
     name: "meta.function-call.python"
+    comment: "Regular function call of the type \"name(args)\""
     begin: '''
       (?x)
         \\b(?=
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 81d6e2d7..5038a69c 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -521,6 +521,10 @@ it's probably control flow like:
             <key>include</key>
             <string>#list</string>
           </dict>
+          <dict>
+            <key>include</key>
+            <string>#odd-function-call</string>
+          </dict>
           <dict>
             <key>include</key>
             <string>#round-braces</string>
@@ -779,6 +783,36 @@ it's probably control flow like:
           </dict>
         </array>
       </dict>
+      <key>odd-function-call</key>
+      <dict>
+        <key>comment</key>
+        <string>A bit obscured function call where there may have been an
+arbitrary number of other operations to get the function.
+E.g. "arr[idx](args)"
+</string>
+        <key>begin</key>
+        <string>(?x)
+  (?&lt;= \] | \) ) \s*
+  (?=\()
+</string>
+        <key>end</key>
+        <string>(\))</string>
+        <key>endCaptures</key>
+        <dict>
+          <key>1</key>
+          <dict>
+            <key>name</key>
+            <string>punctuation.definition.arguments.end.python</string>
+          </dict>
+        </dict>
+        <key>patterns</key>
+        <array>
+          <dict>
+            <key>include</key>
+            <string>#function-arguments</string>
+          </dict>
+        </array>
+      </dict>
       <key>round-braces</key>
       <dict>
         <key>begin</key>
@@ -2554,6 +2588,8 @@ it's probably control flow like:
       <dict>
         <key>name</key>
         <string>meta.function-call.python</string>
+        <key>comment</key>
+        <string>Regular function call of the type "name(args)"</string>
         <key>begin</key>
         <string>(?x)
   \b(?=
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index c39cc8d2..1d35a767 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -404,6 +404,7 @@ repository:
       - include: '#curly-braces'
       - include: '#item-access'
       - include: '#list'
+      - include: '#odd-function-call'
       - include: '#round-braces'
       - include: '#function-call'
       - include: '#builtin-functions'
@@ -505,6 +506,21 @@ repository:
     patterns:
       - include: '#expression'
 
+  odd-function-call:
+    comment: |
+      A bit obscured function call where there may have been an
+      arbitrary number of other operations to get the function.
+      E.g. "arr[idx](args)"
+    begin: |
+      (?x)
+        (?<= \] | \) ) \s*
+        (?=\()
+    end: (\))
+    endCaptures:
+      '1': {name: punctuation.definition.arguments.end.python}
+    patterns:
+      - include: '#function-arguments'
+
   round-braces:
     begin: \(
     end: \)
@@ -1230,6 +1246,7 @@ repository:
 
   function-call:
     name: meta.function-call.python
+    comment: Regular function call of the type "name(args)"
     begin: |
       (?x)
         \b(?=
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 2d052ff2..ed69cdfe 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -651,6 +651,77 @@ describe("Grammar Tests", function() {
       expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
     });
 
+  it("test/calls/call11.py", 
+    function() {
+      tokens = grammar.tokenizeLines("id = Field[uuid.UUID] (\n    uuid.UUID,\n    inheritable=False,\n    simpledelta=False,\n    allow_ddl_set=True,\n)")
+      expect(tokens[0][0].value).toBe("id");
+      expect(tokens[0][0].scopes).toEqual(["source.python","support.function.builtin.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("Field");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.item-access.python","meta.indexed-name.python"]);
+      expect(tokens[0][5].value).toBe("[");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][6].value).toBe("uuid");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python"]);
+      expect(tokens[0][7].value).toBe(".");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","meta.member.access.python","punctuation.separator.period.python"]);
+      expect(tokens[0][8].value).toBe("UUID");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","meta.member.access.python","constant.other.caps.python"]);
+      expect(tokens[0][9].value).toBe("]");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][10].value).toBe(" ");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe("(");
+      expect(tokens[0][11].scopes).toEqual(["source.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][1].value).toBe("uuid");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][2].value).toBe(".");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.arguments.python","meta.member.access.python","punctuation.separator.period.python"]);
+      expect(tokens[1][3].value).toBe("UUID");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.arguments.python","meta.member.access.python","constant.other.caps.python"]);
+      expect(tokens[1][4].value).toBe(",");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function-call.arguments.python"]);
+      expect(tokens[2][1].value).toBe("inheritable");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe("False");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.arguments.python","constant.language.python"]);
+      expect(tokens[2][4].value).toBe(",");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][1].value).toBe("simpledelta");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe("False");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.arguments.python","constant.language.python"]);
+      expect(tokens[3][4].value).toBe(",");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python","meta.function-call.arguments.python"]);
+      expect(tokens[4][1].value).toBe("allow_ddl_set");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[4][2].value).toBe("=");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[4][3].value).toBe("True");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.arguments.python","constant.language.python"]);
+      expect(tokens[4][4].value).toBe(",");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[5][0].value).toBe(")");
+      expect(tokens[5][0].scopes).toEqual(["source.python","punctuation.definition.arguments.end.python"]);
+    });
+
   it("test/calls/call2.py", 
     function() {
       tokens = grammar.tokenizeLines("foo(from=1)")
diff --git a/test/calls/call11.py b/test/calls/call11.py
new file mode 100644
index 00000000..3695fc57
--- /dev/null
+++ b/test/calls/call11.py
@@ -0,0 +1,44 @@
+id = Field[uuid.UUID] (
+    uuid.UUID,
+    inheritable=False,
+    simpledelta=False,
+    allow_ddl_set=True,
+)
+
+
+
+
+
+id            : source.python, support.function.builtin.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+Field         : meta.indexed-name.python, meta.item-access.python, source.python
+[             : meta.item-access.python, punctuation.definition.arguments.begin.python, source.python
+uuid          : meta.item-access.arguments.python, meta.item-access.python, source.python
+.             : meta.item-access.arguments.python, meta.item-access.python, meta.member.access.python, punctuation.separator.period.python, source.python
+UUID          : constant.other.caps.python, meta.item-access.arguments.python, meta.item-access.python, meta.member.access.python, source.python
+]             : meta.item-access.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+(             : punctuation.definition.arguments.begin.python, source.python
+              : meta.function-call.arguments.python, source.python
+uuid          : meta.function-call.arguments.python, source.python
+.             : meta.function-call.arguments.python, meta.member.access.python, punctuation.separator.period.python, source.python
+UUID          : constant.other.caps.python, meta.function-call.arguments.python, meta.member.access.python, source.python
+,             : meta.function-call.arguments.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, source.python
+inheritable   : meta.function-call.arguments.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, source.python
+False         : constant.language.python, meta.function-call.arguments.python, source.python
+,             : meta.function-call.arguments.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, source.python
+simpledelta   : meta.function-call.arguments.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, source.python
+False         : constant.language.python, meta.function-call.arguments.python, source.python
+,             : meta.function-call.arguments.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, source.python
+allow_ddl_set : meta.function-call.arguments.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, source.python
+True          : constant.language.python, meta.function-call.arguments.python, source.python
+,             : meta.function-call.arguments.python, punctuation.separator.arguments.python, source.python
+)             : punctuation.definition.arguments.end.python, source.python

From 2ca894f270f92e2bc8f09a2ebdcd482fbb3b1074 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@edgedb.com>
Date: Fri, 1 May 2020 07:49:17 -0400
Subject: [PATCH 58/65] Update the way "in" is scoped.

The "in" keyword is scoped as either `keyword.operator.logical.python`
or as `keyword.control.flow.python` depending on whether it appears as
part of a "for ... in" construct.

Fixes: #193
---
 grammars/MagicPython.cson            | 25 +++++++++
 grammars/MagicPython.tmLanguage      | 42 ++++++++++++++
 grammars/src/MagicPython.syntax.yaml | 15 +++++
 test/atom-spec/python-spec.js        | 83 ++++++++++++++++++++++++----
 test/expressions/expr4.py            |  2 +-
 test/expressions/keywords.py         |  8 ++-
 test/functions/async1.py             |  2 +-
 test/functions/decl4.py              |  2 +-
 test/statements/for1.py              |  2 +-
 test/statements/for2.py              | 35 ++++++++++++
 test/strings/bug1.py                 |  2 +-
 11 files changed, 200 insertions(+), 18 deletions(-)
 create mode 100644 test/statements/for2.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index c3a2a5f5..1e776684 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -46,6 +46,9 @@ repository:
       {
         include: "#function-declaration"
       }
+      {
+        include: "#generator"
+      }
       {
         include: "#statement-keyword"
       }
@@ -328,6 +331,9 @@ repository:
       {
         include: "#lambda"
       }
+      {
+        include: "#generator"
+      }
       {
         include: "#illegal-operator"
       }
@@ -1318,6 +1324,25 @@ repository:
         include: "#expression"
       }
     ]
+  generator:
+    comment: '''
+      Match "for ... in" construct used in generators and for loops to
+      correctly identify the "in" as a control flow keyword.
+      
+    '''
+    begin: "for"
+    beginCaptures:
+      "0":
+        name: "keyword.control.flow.python"
+    end: "in"
+    endCaptures:
+      "0":
+        name: "keyword.control.flow.python"
+    patterns: [
+      {
+        include: "#expression"
+      }
+    ]
   "function-declaration":
     name: "meta.function.python"
     begin: '''
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 5038a69c..cbc2f0ba 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -69,6 +69,10 @@
             <key>include</key>
             <string>#function-declaration</string>
           </dict>
+          <dict>
+            <key>include</key>
+            <string>#generator</string>
+          </dict>
           <dict>
             <key>include</key>
             <string>#statement-keyword</string>
@@ -501,6 +505,10 @@ it's probably control flow like:
             <key>include</key>
             <string>#lambda</string>
           </dict>
+          <dict>
+            <key>include</key>
+            <string>#generator</string>
+          </dict>
           <dict>
             <key>include</key>
             <string>#illegal-operator</string>
@@ -2046,6 +2054,40 @@ E.g. "arr[idx](args)"
           </dict>
         </array>
       </dict>
+      <key>generator</key>
+      <dict>
+        <key>comment</key>
+        <string>Match "for ... in" construct used in generators and for loops to
+correctly identify the "in" as a control flow keyword.
+</string>
+        <key>begin</key>
+        <string>for</string>
+        <key>beginCaptures</key>
+        <dict>
+          <key>0</key>
+          <dict>
+            <key>name</key>
+            <string>keyword.control.flow.python</string>
+          </dict>
+        </dict>
+        <key>end</key>
+        <string>in</string>
+        <key>endCaptures</key>
+        <dict>
+          <key>0</key>
+          <dict>
+            <key>name</key>
+            <string>keyword.control.flow.python</string>
+          </dict>
+        </dict>
+        <key>patterns</key>
+        <array>
+          <dict>
+            <key>include</key>
+            <string>#expression</string>
+          </dict>
+        </array>
+      </dict>
       <key>function-declaration</key>
       <dict>
         <key>name</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 1d35a767..778e7b1f 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -221,6 +221,7 @@ repository:
       - include: '#import'
       - include: '#class-declaration'
       - include: '#function-declaration'
+      - include: '#generator'
       - include: '#statement-keyword'
       - include: '#assignment-operator'
       - include: '#decorator'
@@ -399,6 +400,7 @@ repository:
       - include: '#regexp'
       - include: '#string'
       - include: '#lambda'
+      - include: '#generator'
       - include: '#illegal-operator'
       - include: '#operator'
       - include: '#curly-braces'
@@ -1040,6 +1042,19 @@ repository:
     patterns:
       - include: '#expression'
 
+  generator:
+    comment: |
+      Match "for ... in" construct used in generators and for loops to
+      correctly identify the "in" as a control flow keyword.
+    begin: for
+    beginCaptures:
+      '0': {name: keyword.control.flow.python}
+    end: in
+    endCaptures:
+      '0': {name: keyword.control.flow.python}
+    patterns:
+      - include: '#expression'
+
   function-declaration:
     name: meta.function.python
     begin: |
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index ed69cdfe..5fe7f9a2 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -5865,7 +5865,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][10].value).toBe(" ");
       expect(tokens[0][10].scopes).toEqual(["source.python"]);
       expect(tokens[0][11].value).toBe("in");
-      expect(tokens[0][11].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[0][11].scopes).toEqual(["source.python","keyword.control.flow.python"]);
       expect(tokens[0][12].value).toBe(" ");
       expect(tokens[0][12].scopes).toEqual(["source.python"]);
       expect(tokens[0][13].value).toBe("range");
@@ -6147,7 +6147,7 @@ describe("Grammar Tests", function() {
 
   it("test/expressions/keywords.py", 
     function() {
-      tokens = grammar.tokenizeLines("as async await continue del assert break finally for\nfrom elif else if import except pass raise\nreturn try while with\n\nnonlocal global class def")
+      tokens = grammar.tokenizeLines("as async await continue del assert break finally\nfrom elif else if import except pass raise\nreturn try while with\n\nnonlocal global class def\n\nfor")
       expect(tokens[0][0].value).toBe("as");
       expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[0][1].value).toBe(" ");
@@ -6178,10 +6178,6 @@ describe("Grammar Tests", function() {
       expect(tokens[0][13].scopes).toEqual(["source.python"]);
       expect(tokens[0][14].value).toBe("finally");
       expect(tokens[0][14].scopes).toEqual(["source.python","keyword.control.flow.python"]);
-      expect(tokens[0][15].value).toBe(" ");
-      expect(tokens[0][15].scopes).toEqual(["source.python"]);
-      expect(tokens[0][16].value).toBe("for");
-      expect(tokens[0][16].scopes).toEqual(["source.python","keyword.control.flow.python"]);
       expect(tokens[1][0].value).toBe("from");
       expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.import.python"]);
       expect(tokens[1][1].value).toBe(" ");
@@ -6240,6 +6236,10 @@ describe("Grammar Tests", function() {
       expect(tokens[4][4].scopes).toEqual(["source.python","storage.type.class.python"]);
       expect(tokens[4][5].value).toBe(" def");
       expect(tokens[4][5].scopes).toEqual(["source.python","storage.type.function.python"]);
+      expect(tokens[5][0].value).toBe("");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][0].value).toBe("for");
+      expect(tokens[6][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
     });
 
   it("test/expressions/special1.py", 
@@ -7988,7 +7988,7 @@ describe("Grammar Tests", function() {
       expect(tokens[3][12].value).toBe(" ");
       expect(tokens[3][12].scopes).toEqual(["source.python"]);
       expect(tokens[3][13].value).toBe("in");
-      expect(tokens[3][13].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[3][13].scopes).toEqual(["source.python","keyword.control.flow.python"]);
       expect(tokens[3][14].value).toBe(" ");
       expect(tokens[3][14].scopes).toEqual(["source.python"]);
       expect(tokens[3][15].value).toBe("b");
@@ -8735,7 +8735,7 @@ describe("Grammar Tests", function() {
       expect(tokens[4][7].value).toBe(" ");
       expect(tokens[4][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
       expect(tokens[4][8].value).toBe("in");
-      expect(tokens[4][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.logical.python"]);
+      expect(tokens[4][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.control.flow.python"]);
       expect(tokens[5][0].value).toBe("                            ");
       expect(tokens[5][0].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
       expect(tokens[5][1].value).toBe("(");
@@ -12165,7 +12165,7 @@ describe("Grammar Tests", function() {
       expect(tokens[0][9].value).toBe(" ");
       expect(tokens[0][9].scopes).toEqual(["source.python"]);
       expect(tokens[0][10].value).toBe("in");
-      expect(tokens[0][10].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[0][10].scopes).toEqual(["source.python","keyword.control.flow.python"]);
       expect(tokens[0][11].value).toBe(" ");
       expect(tokens[0][11].scopes).toEqual(["source.python"]);
       expect(tokens[0][12].value).toBe("b");
@@ -12190,6 +12190,69 @@ describe("Grammar Tests", function() {
       expect(tokens[3][3].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
     });
 
+  it("test/statements/for2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("for a, b, c in [2 in q, 2 in w]:\n    pass")
+      expect(tokens[0][0].value).toBe("for");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("a");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(",");
+      expect(tokens[0][3].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("b");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe(",");
+      expect(tokens[0][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("c");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("in");
+      expect(tokens[0][10].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][11].value).toBe(" ");
+      expect(tokens[0][11].scopes).toEqual(["source.python"]);
+      expect(tokens[0][12].value).toBe("[");
+      expect(tokens[0][12].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[0][13].value).toBe("2");
+      expect(tokens[0][13].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][14].value).toBe(" ");
+      expect(tokens[0][14].scopes).toEqual(["source.python"]);
+      expect(tokens[0][15].value).toBe("in");
+      expect(tokens[0][15].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[0][16].value).toBe(" ");
+      expect(tokens[0][16].scopes).toEqual(["source.python"]);
+      expect(tokens[0][17].value).toBe("q");
+      expect(tokens[0][17].scopes).toEqual(["source.python"]);
+      expect(tokens[0][18].value).toBe(",");
+      expect(tokens[0][18].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][19].value).toBe(" ");
+      expect(tokens[0][19].scopes).toEqual(["source.python"]);
+      expect(tokens[0][20].value).toBe("2");
+      expect(tokens[0][20].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][21].value).toBe(" ");
+      expect(tokens[0][21].scopes).toEqual(["source.python"]);
+      expect(tokens[0][22].value).toBe("in");
+      expect(tokens[0][22].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[0][23].value).toBe(" ");
+      expect(tokens[0][23].scopes).toEqual(["source.python"]);
+      expect(tokens[0][24].value).toBe("w");
+      expect(tokens[0][24].scopes).toEqual(["source.python"]);
+      expect(tokens[0][25].value).toBe("]");
+      expect(tokens[0][25].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[0][26].value).toBe(":");
+      expect(tokens[0][26].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("pass");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
   it("test/statements/from1.py", 
     function() {
       tokens = grammar.tokenizeLines("from ... import foo as bar\nraise Exception('done') from exc\nyield from foo")
@@ -13271,7 +13334,7 @@ describe("Grammar Tests", function() {
       expect(tokens[2][21].value).toBe(" ");
       expect(tokens[2][21].scopes).toEqual(["source.python"]);
       expect(tokens[2][22].value).toBe("in");
-      expect(tokens[2][22].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[2][22].scopes).toEqual(["source.python","keyword.control.flow.python"]);
       expect(tokens[2][23].value).toBe(" ");
       expect(tokens[2][23].scopes).toEqual(["source.python"]);
       expect(tokens[2][24].value).toBe("foo");
diff --git a/test/expressions/expr4.py b/test/expressions/expr4.py
index 6795c76d..ac5e5ddc 100644
--- a/test/expressions/expr4.py
+++ b/test/expressions/expr4.py
@@ -13,7 +13,7 @@
               : source.python
 i             : source.python
               : source.python
-in            : keyword.operator.logical.python, source.python
+in            : keyword.control.flow.python, source.python
               : source.python
 range         : meta.function-call.python, source.python, support.function.builtin.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
diff --git a/test/expressions/keywords.py b/test/expressions/keywords.py
index 6ff1d516..7c14d5c2 100644
--- a/test/expressions/keywords.py
+++ b/test/expressions/keywords.py
@@ -1,9 +1,11 @@
-as async await continue del assert break finally for
+as async await continue del assert break finally
 from elif else if import except pass raise
 return try while with
 
 nonlocal global class def
 
+for
+
 
 
 as            : keyword.control.import.python, source.python
@@ -21,8 +23,6 @@
 break         : keyword.control.flow.python, source.python
               : source.python
 finally       : keyword.control.flow.python, source.python
-              : source.python
-for           : keyword.control.flow.python, source.python
 from          : keyword.control.import.python, source.python
               : source.python
 elif          : keyword.control.flow.python, source.python
@@ -52,3 +52,5 @@
               : source.python
 class         : source.python, storage.type.class.python
  def          : source.python, storage.type.function.python
+              : source.python
+for           : keyword.control.flow.python, source.python
diff --git a/test/functions/async1.py b/test/functions/async1.py
index d6a5546b..0218fafd 100644
--- a/test/functions/async1.py
+++ b/test/functions/async1.py
@@ -36,7 +36,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : source.python
 c             : source.python
               : source.python
-in            : keyword.operator.logical.python, source.python
+in            : keyword.control.flow.python, source.python
               : source.python
 b             : source.python
 :             : punctuation.separator.colon.python, source.python
diff --git a/test/functions/decl4.py b/test/functions/decl4.py
index f3b40fe5..5a452ea4 100644
--- a/test/functions/decl4.py
+++ b/test/functions/decl4.py
@@ -38,7 +38,7 @@ def           : meta.function.python, source.python, storage.type.function.pytho
               : meta.function.parameters.python, meta.function.python, source.python
 val           : meta.function.parameters.python, meta.function.python, source.python
               : meta.function.parameters.python, meta.function.python, source.python
-in            : keyword.operator.logical.python, meta.function.parameters.python, meta.function.python, source.python
+in            : keyword.control.flow.python, meta.function.parameters.python, meta.function.python, source.python
                              : meta.function.parameters.python, meta.function.python, source.python
 (             : meta.function.parameters.python, meta.function.python, punctuation.parenthesis.begin.python, source.python
 x             : meta.function.parameters.python, meta.function.python, source.python
diff --git a/test/statements/for1.py b/test/statements/for1.py
index 3300f8cb..b379ef19 100644
--- a/test/statements/for1.py
+++ b/test/statements/for1.py
@@ -15,7 +15,7 @@
               : source.python
 c             : source.python
               : source.python
-in            : keyword.operator.logical.python, source.python
+in            : keyword.control.flow.python, source.python
               : source.python
 b             : source.python
 :             : punctuation.separator.colon.python, source.python
diff --git a/test/statements/for2.py b/test/statements/for2.py
new file mode 100644
index 00000000..53b826d2
--- /dev/null
+++ b/test/statements/for2.py
@@ -0,0 +1,35 @@
+for a, b, c in [2 in q, 2 in w]:
+    pass
+
+
+
+
+for           : keyword.control.flow.python, source.python
+              : source.python
+a             : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+b             : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+c             : source.python
+              : source.python
+in            : keyword.control.flow.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+2             : constant.numeric.dec.python, source.python
+              : source.python
+in            : keyword.operator.logical.python, source.python
+              : source.python
+q             : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+2             : constant.numeric.dec.python, source.python
+              : source.python
+in            : keyword.operator.logical.python, source.python
+              : source.python
+w             : source.python
+]             : punctuation.definition.list.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+pass          : keyword.control.flow.python, source.python
diff --git a/test/strings/bug1.py b/test/strings/bug1.py
index 9b43c6de..eeb0f950 100644
--- a/test/strings/bug1.py
+++ b/test/strings/bug1.py
@@ -35,7 +35,7 @@
               : source.python
 v             : source.python
               : source.python
-in            : keyword.operator.logical.python, source.python
+in            : keyword.control.flow.python, source.python
               : source.python
 foo           : source.python
               : source.python

From b4b2e6eb16fee36aea0788bf0aa1853c25f7d276 Mon Sep 17 00:00:00 2001
From: Ilia Novoselov <ilya.novoselov@gmail.com>
Date: Mon, 18 May 2020 23:51:23 +0500
Subject: [PATCH 59/65] Fix for loop highlighting #211 (#212)

---
 grammars/MagicPython.cson            |   4 +-
 grammars/MagicPython.tmLanguage      |   4 +-
 grammars/src/MagicPython.syntax.yaml |   4 +-
 test/atom-spec/python-spec.js        | 159 ++++++++++++++++++++-------
 test/statements/for2.py              |  11 +-
 test/statements/for3.py              |  38 +++++++
 6 files changed, 176 insertions(+), 44 deletions(-)
 create mode 100644 test/statements/for3.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 1e776684..26b9698c 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -1330,11 +1330,11 @@ repository:
       correctly identify the "in" as a control flow keyword.
       
     '''
-    begin: "for"
+    begin: "\\bfor\\b"
     beginCaptures:
       "0":
         name: "keyword.control.flow.python"
-    end: "in"
+    end: "\\bin\\b"
     endCaptures:
       "0":
         name: "keyword.control.flow.python"
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index cbc2f0ba..d89bd165 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -2061,7 +2061,7 @@ E.g. "arr[idx](args)"
 correctly identify the "in" as a control flow keyword.
 </string>
         <key>begin</key>
-        <string>for</string>
+        <string>\bfor\b</string>
         <key>beginCaptures</key>
         <dict>
           <key>0</key>
@@ -2071,7 +2071,7 @@ correctly identify the "in" as a control flow keyword.
           </dict>
         </dict>
         <key>end</key>
-        <string>in</string>
+        <string>\bin\b</string>
         <key>endCaptures</key>
         <dict>
           <key>0</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 778e7b1f..065d0873 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -1046,10 +1046,10 @@ repository:
     comment: |
       Match "for ... in" construct used in generators and for loops to
       correctly identify the "in" as a control flow keyword.
-    begin: for
+    begin: \bfor\b
     beginCaptures:
       '0': {name: keyword.control.flow.python}
-    end: in
+    end: \bin\b
     endCaptures:
       '0': {name: keyword.control.flow.python}
     patterns:
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 5fe7f9a2..032c3682 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -12192,11 +12192,90 @@ describe("Grammar Tests", function() {
 
   it("test/statements/for2.py", 
     function() {
-      tokens = grammar.tokenizeLines("for a, b, c in [2 in q, 2 in w]:\n    pass")
-      expect(tokens[0][0].value).toBe("for");
-      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      tokens = grammar.tokenizeLines("forvariable = None\nfor a, b, c, invariable in [2 in q, 2 in w]:\n    pass")
+      expect(tokens[0][0].value).toBe("forvariable");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
       expect(tokens[0][1].value).toBe(" ");
       expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("None");
+      expect(tokens[0][4].scopes).toEqual(["source.python","constant.language.python"]);
+      expect(tokens[1][0].value).toBe("for");
+      expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("a");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe(",");
+      expect(tokens[1][3].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[1][4].value).toBe(" ");
+      expect(tokens[1][4].scopes).toEqual(["source.python"]);
+      expect(tokens[1][5].value).toBe("b");
+      expect(tokens[1][5].scopes).toEqual(["source.python"]);
+      expect(tokens[1][6].value).toBe(",");
+      expect(tokens[1][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[1][7].value).toBe(" ");
+      expect(tokens[1][7].scopes).toEqual(["source.python"]);
+      expect(tokens[1][8].value).toBe("c");
+      expect(tokens[1][8].scopes).toEqual(["source.python"]);
+      expect(tokens[1][9].value).toBe(",");
+      expect(tokens[1][9].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[1][10].value).toBe(" ");
+      expect(tokens[1][10].scopes).toEqual(["source.python"]);
+      expect(tokens[1][11].value).toBe("invariable");
+      expect(tokens[1][11].scopes).toEqual(["source.python"]);
+      expect(tokens[1][12].value).toBe(" ");
+      expect(tokens[1][12].scopes).toEqual(["source.python"]);
+      expect(tokens[1][13].value).toBe("in");
+      expect(tokens[1][13].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][14].value).toBe(" ");
+      expect(tokens[1][14].scopes).toEqual(["source.python"]);
+      expect(tokens[1][15].value).toBe("[");
+      expect(tokens[1][15].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[1][16].value).toBe("2");
+      expect(tokens[1][16].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][17].value).toBe(" ");
+      expect(tokens[1][17].scopes).toEqual(["source.python"]);
+      expect(tokens[1][18].value).toBe("in");
+      expect(tokens[1][18].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[1][19].value).toBe(" ");
+      expect(tokens[1][19].scopes).toEqual(["source.python"]);
+      expect(tokens[1][20].value).toBe("q");
+      expect(tokens[1][20].scopes).toEqual(["source.python"]);
+      expect(tokens[1][21].value).toBe(",");
+      expect(tokens[1][21].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[1][22].value).toBe(" ");
+      expect(tokens[1][22].scopes).toEqual(["source.python"]);
+      expect(tokens[1][23].value).toBe("2");
+      expect(tokens[1][23].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][24].value).toBe(" ");
+      expect(tokens[1][24].scopes).toEqual(["source.python"]);
+      expect(tokens[1][25].value).toBe("in");
+      expect(tokens[1][25].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[1][26].value).toBe(" ");
+      expect(tokens[1][26].scopes).toEqual(["source.python"]);
+      expect(tokens[1][27].value).toBe("w");
+      expect(tokens[1][27].scopes).toEqual(["source.python"]);
+      expect(tokens[1][28].value).toBe("]");
+      expect(tokens[1][28].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[1][29].value).toBe(":");
+      expect(tokens[1][29].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("pass");
+      expect(tokens[2][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
+  it("test/statements/for3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("for(a, b), c, invariable in[2 in q, 2 in w]:\n    pass")
+      expect(tokens[0][0].value).toBe("for");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe("(");
+      expect(tokens[0][1].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
       expect(tokens[0][2].value).toBe("a");
       expect(tokens[0][2].scopes).toEqual(["source.python"]);
       expect(tokens[0][3].value).toBe(",");
@@ -12205,48 +12284,54 @@ describe("Grammar Tests", function() {
       expect(tokens[0][4].scopes).toEqual(["source.python"]);
       expect(tokens[0][5].value).toBe("b");
       expect(tokens[0][5].scopes).toEqual(["source.python"]);
-      expect(tokens[0][6].value).toBe(",");
-      expect(tokens[0][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
-      expect(tokens[0][7].value).toBe(" ");
-      expect(tokens[0][7].scopes).toEqual(["source.python"]);
-      expect(tokens[0][8].value).toBe("c");
+      expect(tokens[0][6].value).toBe(")");
+      expect(tokens[0][6].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[0][7].value).toBe(",");
+      expect(tokens[0][7].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][8].value).toBe(" ");
       expect(tokens[0][8].scopes).toEqual(["source.python"]);
-      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].value).toBe("c");
       expect(tokens[0][9].scopes).toEqual(["source.python"]);
-      expect(tokens[0][10].value).toBe("in");
-      expect(tokens[0][10].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][10].value).toBe(",");
+      expect(tokens[0][10].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
       expect(tokens[0][11].value).toBe(" ");
       expect(tokens[0][11].scopes).toEqual(["source.python"]);
-      expect(tokens[0][12].value).toBe("[");
-      expect(tokens[0][12].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
-      expect(tokens[0][13].value).toBe("2");
-      expect(tokens[0][13].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
-      expect(tokens[0][14].value).toBe(" ");
-      expect(tokens[0][14].scopes).toEqual(["source.python"]);
-      expect(tokens[0][15].value).toBe("in");
-      expect(tokens[0][15].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
-      expect(tokens[0][16].value).toBe(" ");
-      expect(tokens[0][16].scopes).toEqual(["source.python"]);
-      expect(tokens[0][17].value).toBe("q");
+      expect(tokens[0][12].value).toBe("invariable");
+      expect(tokens[0][12].scopes).toEqual(["source.python"]);
+      expect(tokens[0][13].value).toBe(" ");
+      expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[0][14].value).toBe("in");
+      expect(tokens[0][14].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][15].value).toBe("[");
+      expect(tokens[0][15].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[0][16].value).toBe("2");
+      expect(tokens[0][16].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][17].value).toBe(" ");
       expect(tokens[0][17].scopes).toEqual(["source.python"]);
-      expect(tokens[0][18].value).toBe(",");
-      expect(tokens[0][18].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][18].value).toBe("in");
+      expect(tokens[0][18].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
       expect(tokens[0][19].value).toBe(" ");
       expect(tokens[0][19].scopes).toEqual(["source.python"]);
-      expect(tokens[0][20].value).toBe("2");
-      expect(tokens[0][20].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
-      expect(tokens[0][21].value).toBe(" ");
-      expect(tokens[0][21].scopes).toEqual(["source.python"]);
-      expect(tokens[0][22].value).toBe("in");
-      expect(tokens[0][22].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
-      expect(tokens[0][23].value).toBe(" ");
-      expect(tokens[0][23].scopes).toEqual(["source.python"]);
-      expect(tokens[0][24].value).toBe("w");
+      expect(tokens[0][20].value).toBe("q");
+      expect(tokens[0][20].scopes).toEqual(["source.python"]);
+      expect(tokens[0][21].value).toBe(",");
+      expect(tokens[0][21].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[0][22].value).toBe(" ");
+      expect(tokens[0][22].scopes).toEqual(["source.python"]);
+      expect(tokens[0][23].value).toBe("2");
+      expect(tokens[0][23].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[0][24].value).toBe(" ");
       expect(tokens[0][24].scopes).toEqual(["source.python"]);
-      expect(tokens[0][25].value).toBe("]");
-      expect(tokens[0][25].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
-      expect(tokens[0][26].value).toBe(":");
-      expect(tokens[0][26].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[0][25].value).toBe("in");
+      expect(tokens[0][25].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[0][26].value).toBe(" ");
+      expect(tokens[0][26].scopes).toEqual(["source.python"]);
+      expect(tokens[0][27].value).toBe("w");
+      expect(tokens[0][27].scopes).toEqual(["source.python"]);
+      expect(tokens[0][28].value).toBe("]");
+      expect(tokens[0][28].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[0][29].value).toBe(":");
+      expect(tokens[0][29].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
       expect(tokens[1][0].value).toBe("    ");
       expect(tokens[1][0].scopes).toEqual(["source.python"]);
       expect(tokens[1][1].value).toBe("pass");
diff --git a/test/statements/for2.py b/test/statements/for2.py
index 53b826d2..8468e08e 100644
--- a/test/statements/for2.py
+++ b/test/statements/for2.py
@@ -1,9 +1,15 @@
-for a, b, c in [2 in q, 2 in w]:
+forvariable = None
+for a, b, c, invariable in [2 in q, 2 in w]:
     pass
 
 
 
 
+forvariable   : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+None          : constant.language.python, source.python
 for           : keyword.control.flow.python, source.python
               : source.python
 a             : source.python
@@ -13,6 +19,9 @@
 ,             : punctuation.separator.element.python, source.python
               : source.python
 c             : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+invariable    : source.python
               : source.python
 in            : keyword.control.flow.python, source.python
               : source.python
diff --git a/test/statements/for3.py b/test/statements/for3.py
new file mode 100644
index 00000000..5ebfc592
--- /dev/null
+++ b/test/statements/for3.py
@@ -0,0 +1,38 @@
+for(a, b), c, invariable in[2 in q, 2 in w]:
+    pass
+
+
+
+
+for           : keyword.control.flow.python, source.python
+(             : punctuation.parenthesis.begin.python, source.python
+a             : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+b             : source.python
+)             : punctuation.parenthesis.end.python, source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+c             : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+invariable    : source.python
+              : source.python
+in            : keyword.control.flow.python, source.python
+[             : punctuation.definition.list.begin.python, source.python
+2             : constant.numeric.dec.python, source.python
+              : source.python
+in            : keyword.operator.logical.python, source.python
+              : source.python
+q             : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+2             : constant.numeric.dec.python, source.python
+              : source.python
+in            : keyword.operator.logical.python, source.python
+              : source.python
+w             : source.python
+]             : punctuation.definition.list.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+pass          : keyword.control.flow.python, source.python

From 225fa4c4e3d8bfe450e52ab03660851bcb99a705 Mon Sep 17 00:00:00 2001
From: Anthony Sottile <asottile@umich.edu>
Date: Fri, 21 Feb 2020 20:58:14 -0800
Subject: [PATCH 60/65] constant.numeric.dec.python only has 2 capture groups

---
 grammars/MagicPython.cson            | 2 --
 grammars/MagicPython.tmLanguage      | 5 -----
 grammars/src/MagicPython.syntax.yaml | 1 -
 3 files changed, 8 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 26b9698c..6e75a4af 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -719,8 +719,6 @@ repository:
         name: "storage.type.imaginary.number.python"
       "2":
         name: "invalid.illegal.dec.python"
-      "3":
-        name: "invalid.illegal.dec.python"
   "number-hex":
     name: "constant.numeric.hex.python"
     match: '''
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index d89bd165..fec12e3c 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -1092,11 +1092,6 @@ E.g. "arr[idx](args)"
             <key>name</key>
             <string>invalid.illegal.dec.python</string>
           </dict>
-          <key>3</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.dec.python</string>
-          </dict>
         </dict>
       </dict>
       <key>number-hex</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 065d0873..32186e92 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -650,7 +650,6 @@ repository:
     captures:
       '1': {name: storage.type.imaginary.number.python}
       '2': {name: invalid.illegal.dec.python}
-      '3': {name: invalid.illegal.dec.python}
 
   number-hex:
     name: constant.numeric.hex.python

From b2b4f4ae7b4e6284e80bda8080106b93bd588f9e Mon Sep 17 00:00:00 2001
From: Paul Chaignon <paul.chaignon@gmail.com>
Date: Sat, 16 Dec 2017 12:45:51 +0100
Subject: [PATCH 61/65] Remove invalid first_line_match key

---
 grammars/MagicPython.cson            | 1 -
 grammars/MagicPython.tmLanguage      | 2 --
 grammars/src/MagicPython.syntax.yaml | 1 -
 3 files changed, 4 deletions(-)

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 6e75a4af..6486dba4 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -20,7 +20,6 @@ fileTypes: [
   "smk"
   "tac"
 ]
-first_line_match: "^#![ \\t]*/.*\\bpython[\\d\\.]*\\b"
 firstLineMatch: "^#![ \\t]*/.*\\bpython[\\d\\.]*\\b"
 uuid: "742deb57-6e38-4192-bed6-410746efd85d"
 patterns: [
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index fec12e3c..5a07f545 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -27,8 +27,6 @@
       <string>smk</string>
       <string>tac</string>
     </array>
-    <key>first_line_match</key>
-    <string>^#![ \t]*/.*\bpython[\d\.]*\b</string>
     <key>firstLineMatch</key>
     <string>^#![ \t]*/.*\bpython[\d\.]*\b</string>
     <key>uuid</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 32186e92..9c80c8b3 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -5,7 +5,6 @@ scopeName: source.python
 fileTypes: [py, py3, rpy, pyw, cpy, pyi,
             SConstruct, Sconstruct, sconstruct, SConscript,
             gyp, gypi, wsgi, kv, Snakefile, smk, tac]
-first_line_match: ^#![ \t]*/.*\bpython[\d\.]*\b
 firstLineMatch: ^#![ \t]*/.*\bpython[\d\.]*\b
 uuid: 742deb57-6e38-4192-bed6-410746efd85d
 

From 2802ded681e0ab1a1057821c1da287147d639505 Mon Sep 17 00:00:00 2001
From: Elvis Pranskevichus <elvis@edgedb.com>
Date: Wed, 11 Nov 2020 18:15:21 -0800
Subject: [PATCH 62/65] Github doesn't seem to use MP for highlighter
 tokenization

MagicPython is still used by Linguist, but the actual syntax
hightlighting seems to be driven by something else now.  Thus, remove
the outdated statement from the README.

Closes: #225
---
 README.md | 2 --
 1 file changed, 2 deletions(-)

diff --git a/README.md b/README.md
index 41a48420..64d9eb43 100644
--- a/README.md
+++ b/README.md
@@ -6,8 +6,6 @@ with [Sublime Text](http://www.sublimetext.com), [Atom](http://atom.io) and
 [Visual Studio Code](http://code.visualstudio.com). It is meant to be a drop-in
 replacement for the default Python package.
 
-We are proud to say that MagicPython is used by GitHub to highlight Python.
-
 **Attention VSCode users**: MagicPython is used as the _default_
 Python highlighter in Visual Studio Code. Don't install it unless you
 want or need the cutting edge version of it. You will likely see no

From db32a0d840b3a44d03596e31a4d5a936d99a8d8a Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@edgedb.com>
Date: Fri, 31 Jul 2020 05:08:47 -0400
Subject: [PATCH 63/65] Add Python 3.8 features.

Add walrus operator `:=`.
Add positional only args separator `/`.
Add `=` to f-string formatting.

Fixes #189
---
 grammars/MagicPython.cson              |  32 +++-
 grammars/MagicPython.tmLanguage        |  43 ++++-
 grammars/src/MagicPython.syntax.yaml   |   7 +
 grammars/src/pyfstring.inc.syntax.yaml |   8 +-
 misc/example.py                        |  12 +-
 misc/scopes                            |   1 +
 test/atom-spec/python-spec.js          | 228 +++++++++++++++++++++++++
 test/expressions/expr21.py             |  39 +++++
 test/fstrings/simple10.py              |  18 ++
 test/functions/decl15.py               |  34 ++++
 test/functions/lambda10.py             |  35 ++++
 11 files changed, 439 insertions(+), 18 deletions(-)
 create mode 100644 test/expressions/expr21.py
 create mode 100644 test/fstrings/simple10.py
 create mode 100644 test/functions/decl15.py
 create mode 100644 test/functions/lambda10.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index 6486dba4..b137f776 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -619,6 +619,8 @@ repository:
       
           | (!= | == | >= | <= | < | >)                          (?# 5)
       
+          | (:=)                                                 (?# 6)
+      
     '''
     captures:
       "1":
@@ -631,6 +633,8 @@ repository:
         name: "keyword.operator.arithmetic.python"
       "5":
         name: "keyword.operator.comparison.python"
+      "6":
+        name: "keyword.operator.assignment.python"
   punctuation:
     patterns: [
       {
@@ -1255,6 +1259,10 @@ repository:
             name: "punctuation.section.function.lambda.begin.python"
         contentName: "meta.function.lambda.parameters.python"
         patterns: [
+          {
+            name: "keyword.operator.positional.parameter.python"
+            match: "/"
+          }
           {
             name: "keyword.operator.unpacking.parameter.python"
             match: "(\\*\\*|\\*)"
@@ -1402,6 +1410,10 @@ repository:
       "1":
         name: "punctuation.definition.parameters.end.python"
     patterns: [
+      {
+        name: "keyword.operator.positional.parameter.python"
+        match: "/"
+      }
       {
         name: "keyword.operator.unpacking.parameter.python"
         match: "(\\*\\*|\\*)"
@@ -4720,12 +4732,16 @@ repository:
     patterns: [
       {
         name: "storage.type.format.python"
-        match: "(![rsa])(?=})"
+        match: "(=(![rsa])?)(?=})"
+      }
+      {
+        name: "storage.type.format.python"
+        match: "(=?![rsa])(?=})"
       }
       {
         match: '''
           (?x)
-            (![rsa])?
+            ( (?: =?) (?: ![rsa])? )
               ( : \\w? [<>=^]? [-+ ]? \\#?
                 \\d* ,? (\\.\\d+)? [bcdeEfFgGnosxX%]? )(?=})
           
@@ -4741,7 +4757,7 @@ repository:
       }
     ]
   "fstring-terminator-single-tail":
-    begin: "(![rsa])?(:)(?=.*?{)"
+    begin: "((?:=?)(?:![rsa])?)(:)(?=.*?{)"
     end: "(?=})|(?=\\n)"
     beginCaptures:
       "1":
@@ -4944,12 +4960,16 @@ repository:
     patterns: [
       {
         name: "storage.type.format.python"
-        match: "(![rsa])(?=})"
+        match: "(=(![rsa])?)(?=})"
+      }
+      {
+        name: "storage.type.format.python"
+        match: "(=?![rsa])(?=})"
       }
       {
         match: '''
           (?x)
-            (![rsa])?
+            ( (?: =?) (?: ![rsa])? )
               ( : \\w? [<>=^]? [-+ ]? \\#?
                 \\d* ,? (\\.\\d+)? [bcdeEfFgGnosxX%]? )(?=})
           
@@ -4965,7 +4985,7 @@ repository:
       }
     ]
   "fstring-terminator-multi-tail":
-    begin: "(![rsa])?(:)(?=.*?{)"
+    begin: "((?:=?)(?:![rsa])?)(:)(?=.*?{)"
     end: "(?=})"
     beginCaptures:
       "1":
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index 5a07f545..a4f973df 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -933,6 +933,8 @@ E.g. "arr[idx](args)"
     | (\*\* | \* | \+ | - | % | // | / | @)                (?# 4)
 
     | (!= | == | &gt;= | &lt;= | &lt; | &gt;)                          (?# 5)
+
+    | (:=)                                                 (?# 6)
 </string>
         <key>captures</key>
         <dict>
@@ -961,6 +963,11 @@ E.g. "arr[idx](args)"
             <key>name</key>
             <string>keyword.operator.comparison.python</string>
           </dict>
+          <key>6</key>
+          <dict>
+            <key>name</key>
+            <string>keyword.operator.assignment.python</string>
+          </dict>
         </dict>
       </dict>
       <key>punctuation</key>
@@ -1936,6 +1943,12 @@ E.g. "arr[idx](args)"
             <string>meta.function.lambda.parameters.python</string>
             <key>patterns</key>
             <array>
+              <dict>
+                <key>name</key>
+                <string>keyword.operator.positional.parameter.python</string>
+                <key>match</key>
+                <string>/</string>
+              </dict>
               <dict>
                 <key>name</key>
                 <string>keyword.operator.unpacking.parameter.python</string>
@@ -2184,6 +2197,12 @@ correctly identify the "in" as a control flow keyword.
         </dict>
         <key>patterns</key>
         <array>
+          <dict>
+            <key>name</key>
+            <string>keyword.operator.positional.parameter.python</string>
+            <key>match</key>
+            <string>/</string>
+          </dict>
           <dict>
             <key>name</key>
             <string>keyword.operator.unpacking.parameter.python</string>
@@ -8259,12 +8278,18 @@ indirectly through syntactic constructs
             <key>name</key>
             <string>storage.type.format.python</string>
             <key>match</key>
-            <string>(![rsa])(?=})</string>
+            <string>(=(![rsa])?)(?=})</string>
+          </dict>
+          <dict>
+            <key>name</key>
+            <string>storage.type.format.python</string>
+            <key>match</key>
+            <string>(=?![rsa])(?=})</string>
           </dict>
           <dict>
             <key>match</key>
             <string>(?x)
-  (![rsa])?
+  ( (?: =?) (?: ![rsa])? )
     ( : \w? [&lt;&gt;=^]? [-+ ]? \#?
       \d* ,? (\.\d+)? [bcdeEfFgGnosxX%]? )(?=})
 </string>
@@ -8291,7 +8316,7 @@ indirectly through syntactic constructs
       <key>fstring-terminator-single-tail</key>
       <dict>
         <key>begin</key>
-        <string>(![rsa])?(:)(?=.*?{)</string>
+        <string>((?:=?)(?:![rsa])?)(:)(?=.*?{)</string>
         <key>end</key>
         <string>(?=})|(?=\n)</string>
         <key>beginCaptures</key>
@@ -8631,12 +8656,18 @@ indirectly through syntactic constructs
             <key>name</key>
             <string>storage.type.format.python</string>
             <key>match</key>
-            <string>(![rsa])(?=})</string>
+            <string>(=(![rsa])?)(?=})</string>
+          </dict>
+          <dict>
+            <key>name</key>
+            <string>storage.type.format.python</string>
+            <key>match</key>
+            <string>(=?![rsa])(?=})</string>
           </dict>
           <dict>
             <key>match</key>
             <string>(?x)
-  (![rsa])?
+  ( (?: =?) (?: ![rsa])? )
     ( : \w? [&lt;&gt;=^]? [-+ ]? \#?
       \d* ,? (\.\d+)? [bcdeEfFgGnosxX%]? )(?=})
 </string>
@@ -8663,7 +8694,7 @@ indirectly through syntactic constructs
       <key>fstring-terminator-multi-tail</key>
       <dict>
         <key>begin</key>
-        <string>(![rsa])?(:)(?=.*?{)</string>
+        <string>((?:=?)(?:![rsa])?)(:)(?=.*?{)</string>
         <key>end</key>
         <string>(?=})</string>
         <key>beginCaptures</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 9c80c8b3..83948dc1 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -582,12 +582,15 @@ repository:
 
           | (!= | == | >= | <= | < | >)                          (?# 5)
 
+          | (:=)                                                 (?# 6)
+
     captures:
       '1': {name: keyword.operator.logical.python}
       '2': {name: keyword.control.flow.python}
       '3': {name: keyword.operator.bitwise.python}
       '4': {name: keyword.operator.arithmetic.python}
       '5': {name: keyword.operator.comparison.python}
+      '6': {name: keyword.operator.assignment.python}
 
   punctuation:
     patterns:
@@ -1002,6 +1005,8 @@ repository:
 
         contentName: meta.function.lambda.parameters.python
         patterns:
+          - name: keyword.operator.positional.parameter.python
+            match: /
           - name: keyword.operator.unpacking.parameter.python
             match: (\*\*|\*)
           - include: '#lambda-nested-incomplete'
@@ -1096,6 +1101,8 @@ repository:
       '1': {name: punctuation.definition.parameters.end.python}
 
     patterns:
+      - name: keyword.operator.positional.parameter.python
+        match: /
       - name: keyword.operator.unpacking.parameter.python
         match: (\*\*|\*)
       - include: '#lambda-incomplete'
diff --git a/grammars/src/pyfstring.inc.syntax.yaml b/grammars/src/pyfstring.inc.syntax.yaml
index 993707cf..e605f17c 100644
--- a/grammars/src/pyfstring.inc.syntax.yaml
+++ b/grammars/src/pyfstring.inc.syntax.yaml
@@ -127,10 +127,12 @@ fstring-${line}-brace:
 fstring-terminator-${line}:
   patterns:
     - name: storage.type.format.python
-      match: (![rsa])(?=})
+      match: (=(![rsa])?)(?=})
+    - name: storage.type.format.python
+      match: (=?![rsa])(?=})
     - match: |
         (?x)
-          (![rsa])?
+          ( (?: =?) (?: ![rsa])? )
             ( : \w? [<>=^]? [-+ ]? \#?
               \d* ,? (\.\d+)? [bcdeEfFgGnosxX%]? )(?=})
       captures:
@@ -148,7 +150,7 @@ fstring-terminator-${line}:
     - include: '#fstring-terminator-${line}-tail'
 
 fstring-terminator-${line}-tail:
-  begin: (![rsa])?(:)(?=.*?{)
+  begin: ((?:=?)(?:![rsa])?)(:)(?=.*?{)
   end: (?=})${fguard}
   beginCaptures:
     '1': {name: storage.type.format.python}
diff --git a/misc/example.py b/misc/example.py
index 6b820e63..e6ea7ad0 100644
--- a/misc/example.py
+++ b/misc/example.py
@@ -1,7 +1,7 @@
 import asyncio
 
 
-def showcase():
+def showcase(a, b, /, c, d, *, e, f):
     """Some code to showcase the syntax.
 
     Docstrings are recognized and have an additional scope.
@@ -21,7 +21,7 @@ async def coroutine(db:aio_db.DatabaseConnection) -> List[str]:
 
         async with db.transaction():
             result = await db.query(...)
-            print(f'Result: {result!r}')
+            print(f'Result: {result!r} {a=} {b=!r}')
 
     mapping = None     # type: Dict[int, Any] # PEP 484
 
@@ -41,8 +41,14 @@ async def coroutine(db:aio_db.DatabaseConnection) -> List[str]:
     # NOTE Numbers with leading zeros are invalid in Python 3,
     # use 0o...
     answer = func(0xdeadbeef + 0b00100001 + 0123 + 0o123 +
-                  1_005_123 + # PEP 515
+                  1_005_123 +  # PEP 515
                   # complex numbers
                   .10e12 + 2j) @ mat
 
+    # walrus operator
+    filtered_data = [y for x in data if (y := f(x)) is not None]
+
+    # position-only params
+    bar = lambda q, w, /, e, r: (q + w + e + r)
+
     return R'''No escapes '\' in this \one'''
diff --git a/misc/scopes b/misc/scopes
index 12785af1..8eec651e 100644
--- a/misc/scopes
+++ b/misc/scopes
@@ -56,6 +56,7 @@ keyword.operator.lookahead.regexp
 keyword.operator.lookbehind.negative.regexp
 keyword.operator.lookbehind.regexp
 keyword.operator.negation.regexp
+keyword.operator.positional.parameter.python
 keyword.operator.python
 keyword.operator.quantifier.regexp
 keyword.operator.unpacking.arguments.python
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index 032c3682..da7d08c1 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -5800,6 +5800,77 @@ describe("Grammar Tests", function() {
       expect(tokens[5][4].scopes).toEqual(["source.python"]);
     });
 
+  it("test/expressions/expr21.py", 
+    function() {
+      tokens = grammar.tokenizeLines("while chunk := file.read(8192):\n   process(chunk)\n   y0 = (y1 := f(x))")
+      expect(tokens[0][0].value).toBe("while");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("chunk");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe(":=");
+      expect(tokens[0][4].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("file");
+      expect(tokens[0][6].scopes).toEqual(["source.python","variable.legacy.builtin.python"]);
+      expect(tokens[0][7].value).toBe(".");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
+      expect(tokens[0][8].value).toBe("read");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][9].value).toBe("(");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][10].value).toBe("8192");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[0][11].value).toBe(")");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][12].value).toBe(":");
+      expect(tokens[0][12].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("   ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("process");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][2].value).toBe("(");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][3].value).toBe("chunk");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][4].value).toBe(")");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][0].value).toBe("   ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("y0");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe("=");
+      expect(tokens[2][3].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][4].value).toBe(" ");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][5].value).toBe("(");
+      expect(tokens[2][5].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[2][6].value).toBe("y1");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][7].value).toBe(" ");
+      expect(tokens[2][7].scopes).toEqual(["source.python"]);
+      expect(tokens[2][8].value).toBe(":=");
+      expect(tokens[2][8].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][9].value).toBe(" ");
+      expect(tokens[2][9].scopes).toEqual(["source.python"]);
+      expect(tokens[2][10].value).toBe("f");
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[2][11].value).toBe("(");
+      expect(tokens[2][11].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][12].value).toBe("x");
+      expect(tokens[2][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[2][13].value).toBe(")");
+      expect(tokens[2][13].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][14].value).toBe(")");
+      expect(tokens[2][14].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+    });
+
   it("test/expressions/expr3.py", 
     function() {
       tokens = grammar.tokenizeLines("(a, *rest, b) = range(5)")
@@ -7490,6 +7561,37 @@ describe("Grammar Tests", function() {
       expect(tokens[2][20].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
     });
 
+  it("test/fstrings/simple10.py", 
+    function() {
+      tokens = grammar.tokenizeLines("f'values: {a=} {b=!r}'")
+      expect(tokens[0][0].value).toBe("f");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("values: ");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][4].value).toBe("a");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][5].value).toBe("=");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][6].value).toBe("}");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][8].value).toBe("{");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][9].value).toBe("b");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][10].value).toBe("=!r");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","storage.type.format.python"]);
+      expect(tokens[0][11].value).toBe("}");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][12].value).toBe("'");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
   it("test/fstrings/simple2.py", 
     function() {
       tokens = grammar.tokenizeLines("a = f\"normal {{ normal }} normal } {10!r} normal {fo.__add__!s}\"")
@@ -8501,6 +8603,67 @@ describe("Grammar Tests", function() {
       expect(tokens[14][9].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
     });
 
+  it("test/functions/decl15.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def showcase(a, b, /, c, d, *, e, f):\n    return")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("showcase");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe("a");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][5].value).toBe(",");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][7].value).toBe("b");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][8].value).toBe(",");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][10].value).toBe("/");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.positional.parameter.python"]);
+      expect(tokens[0][11].value).toBe(", ");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][12].value).toBe("c");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][13].value).toBe(",");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][14].value).toBe(" ");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][15].value).toBe("d");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][16].value).toBe(",");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][17].value).toBe(" ");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][18].value).toBe("*");
+      expect(tokens[0][18].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","keyword.operator.unpacking.parameter.python"]);
+      expect(tokens[0][19].value).toBe(", ");
+      expect(tokens[0][19].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][20].value).toBe("e");
+      expect(tokens[0][20].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][21].value).toBe(",");
+      expect(tokens[0][21].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][22].value).toBe(" ");
+      expect(tokens[0][22].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python"]);
+      expect(tokens[0][23].value).toBe("f");
+      expect(tokens[0][23].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][24].value).toBe(")");
+      expect(tokens[0][24].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][25].value).toBe(":");
+      expect(tokens[0][25].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("return");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+    });
+
   it("test/functions/decl2.py", 
     function() {
       tokens = grammar.tokenizeLines("def result_annot(lambda, lambda=) -> qqq[None]:\n    pass")
@@ -9632,6 +9795,71 @@ describe("Grammar Tests", function() {
       expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
     });
 
+  it("test/functions/lambda10.py", 
+    function() {
+      tokens = grammar.tokenizeLines("showcase = lambda a, /, b, *, c: (a + b + c)")
+      expect(tokens[0][0].value).toBe("showcase");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("lambda");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.lambda-function.python","storage.type.function.lambda.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][6].value).toBe("a");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][7].value).toBe(",");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][8].value).toBe(" ");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][9].value).toBe("/");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","keyword.operator.positional.parameter.python"]);
+      expect(tokens[0][10].value).toBe(", ");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][11].value).toBe("b");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][12].value).toBe(",");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","punctuation.separator.parameters.python"]);
+      expect(tokens[0][13].value).toBe(" ");
+      expect(tokens[0][13].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][14].value).toBe("*");
+      expect(tokens[0][14].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","keyword.operator.unpacking.parameter.python"]);
+      expect(tokens[0][15].value).toBe(", ");
+      expect(tokens[0][15].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python"]);
+      expect(tokens[0][16].value).toBe("c");
+      expect(tokens[0][16].scopes).toEqual(["source.python","meta.lambda-function.python","meta.function.lambda.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][17].value).toBe(":");
+      expect(tokens[0][17].scopes).toEqual(["source.python","meta.lambda-function.python","punctuation.section.function.lambda.begin.python"]);
+      expect(tokens[0][18].value).toBe(" ");
+      expect(tokens[0][18].scopes).toEqual(["source.python"]);
+      expect(tokens[0][19].value).toBe("(");
+      expect(tokens[0][19].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[0][20].value).toBe("a");
+      expect(tokens[0][20].scopes).toEqual(["source.python"]);
+      expect(tokens[0][21].value).toBe(" ");
+      expect(tokens[0][21].scopes).toEqual(["source.python"]);
+      expect(tokens[0][22].value).toBe("+");
+      expect(tokens[0][22].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][23].value).toBe(" ");
+      expect(tokens[0][23].scopes).toEqual(["source.python"]);
+      expect(tokens[0][24].value).toBe("b");
+      expect(tokens[0][24].scopes).toEqual(["source.python"]);
+      expect(tokens[0][25].value).toBe(" ");
+      expect(tokens[0][25].scopes).toEqual(["source.python"]);
+      expect(tokens[0][26].value).toBe("+");
+      expect(tokens[0][26].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][27].value).toBe(" ");
+      expect(tokens[0][27].scopes).toEqual(["source.python"]);
+      expect(tokens[0][28].value).toBe("c");
+      expect(tokens[0][28].scopes).toEqual(["source.python"]);
+      expect(tokens[0][29].value).toBe(")");
+      expect(tokens[0][29].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+    });
+
   it("test/functions/lambda2.py", 
     function() {
       tokens = grammar.tokenizeLines("lll(lambda=1)")
diff --git a/test/expressions/expr21.py b/test/expressions/expr21.py
new file mode 100644
index 00000000..59556710
--- /dev/null
+++ b/test/expressions/expr21.py
@@ -0,0 +1,39 @@
+while chunk := file.read(8192):
+   process(chunk)
+   y0 = (y1 := f(x))
+
+
+
+while         : keyword.control.flow.python, source.python
+              : source.python
+chunk         : source.python
+              : source.python
+:=            : keyword.operator.assignment.python, source.python
+              : source.python
+file          : source.python, variable.legacy.builtin.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+read          : meta.function-call.generic.python, meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+8192          : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, meta.member.access.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+process       : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+chunk         : meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+y0            : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+(             : punctuation.parenthesis.begin.python, source.python
+y1            : source.python
+              : source.python
+:=            : keyword.operator.assignment.python, source.python
+              : source.python
+f             : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+x             : meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+)             : punctuation.parenthesis.end.python, source.python
diff --git a/test/fstrings/simple10.py b/test/fstrings/simple10.py
new file mode 100644
index 00000000..ae793021
--- /dev/null
+++ b/test/fstrings/simple10.py
@@ -0,0 +1,18 @@
+f'values: {a=} {b=!r}'
+
+
+
+
+f             : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
+values:       : meta.fstring.python, source.python, string.interpolated.python, string.quoted.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+a             : meta.fstring.python, source.python
+=             : meta.fstring.python, source.python, storage.type.format.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+              : meta.fstring.python, source.python, string.interpolated.python, string.quoted.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+b             : meta.fstring.python, source.python
+=!r           : meta.fstring.python, source.python, storage.type.format.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
diff --git a/test/functions/decl15.py b/test/functions/decl15.py
new file mode 100644
index 00000000..7f5c4ecc
--- /dev/null
+++ b/test/functions/decl15.py
@@ -0,0 +1,34 @@
+def showcase(a, b, /, c, d, *, e, f):
+    return
+
+
+
+
+def           : meta.function.python, source.python, storage.type.function.python
+              : meta.function.python, source.python
+showcase      : entity.name.function.python, meta.function.python, source.python
+(             : meta.function.parameters.python, meta.function.python, punctuation.definition.parameters.begin.python, source.python
+a             : meta.function.parameters.python, meta.function.python, source.python, variable.parameter.function.language.python
+,             : meta.function.parameters.python, meta.function.python, punctuation.separator.parameters.python, source.python
+              : meta.function.parameters.python, meta.function.python, source.python
+b             : meta.function.parameters.python, meta.function.python, source.python, variable.parameter.function.language.python
+,             : meta.function.parameters.python, meta.function.python, punctuation.separator.parameters.python, source.python
+              : meta.function.parameters.python, meta.function.python, source.python
+/             : keyword.operator.positional.parameter.python, meta.function.parameters.python, meta.function.python, source.python
+,             : meta.function.parameters.python, meta.function.python, source.python
+c             : meta.function.parameters.python, meta.function.python, source.python, variable.parameter.function.language.python
+,             : meta.function.parameters.python, meta.function.python, punctuation.separator.parameters.python, source.python
+              : meta.function.parameters.python, meta.function.python, source.python
+d             : meta.function.parameters.python, meta.function.python, source.python, variable.parameter.function.language.python
+,             : meta.function.parameters.python, meta.function.python, punctuation.separator.parameters.python, source.python
+              : meta.function.parameters.python, meta.function.python, source.python
+*             : keyword.operator.unpacking.parameter.python, meta.function.parameters.python, meta.function.python, source.python
+,             : meta.function.parameters.python, meta.function.python, source.python
+e             : meta.function.parameters.python, meta.function.python, source.python, variable.parameter.function.language.python
+,             : meta.function.parameters.python, meta.function.python, punctuation.separator.parameters.python, source.python
+              : meta.function.parameters.python, meta.function.python, source.python
+f             : meta.function.parameters.python, meta.function.python, source.python, variable.parameter.function.language.python
+)             : meta.function.parameters.python, meta.function.python, punctuation.definition.parameters.end.python, source.python
+:             : meta.function.python, punctuation.section.function.begin.python, source.python
+              : source.python
+return        : keyword.control.flow.python, source.python
diff --git a/test/functions/lambda10.py b/test/functions/lambda10.py
new file mode 100644
index 00000000..c033ac71
--- /dev/null
+++ b/test/functions/lambda10.py
@@ -0,0 +1,35 @@
+showcase = lambda a, /, b, *, c: (a + b + c)
+
+
+
+
+showcase      : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+lambda        : meta.lambda-function.python, source.python, storage.type.function.lambda.python
+              : meta.function.lambda.parameters.python, meta.lambda-function.python, source.python
+a             : meta.function.lambda.parameters.python, meta.lambda-function.python, source.python, variable.parameter.function.language.python
+,             : meta.function.lambda.parameters.python, meta.lambda-function.python, punctuation.separator.parameters.python, source.python
+              : meta.function.lambda.parameters.python, meta.lambda-function.python, source.python
+/             : keyword.operator.positional.parameter.python, meta.function.lambda.parameters.python, meta.lambda-function.python, source.python
+,             : meta.function.lambda.parameters.python, meta.lambda-function.python, source.python
+b             : meta.function.lambda.parameters.python, meta.lambda-function.python, source.python, variable.parameter.function.language.python
+,             : meta.function.lambda.parameters.python, meta.lambda-function.python, punctuation.separator.parameters.python, source.python
+              : meta.function.lambda.parameters.python, meta.lambda-function.python, source.python
+*             : keyword.operator.unpacking.parameter.python, meta.function.lambda.parameters.python, meta.lambda-function.python, source.python
+,             : meta.function.lambda.parameters.python, meta.lambda-function.python, source.python
+c             : meta.function.lambda.parameters.python, meta.lambda-function.python, source.python, variable.parameter.function.language.python
+:             : meta.lambda-function.python, punctuation.section.function.lambda.begin.python, source.python
+              : source.python
+(             : punctuation.parenthesis.begin.python, source.python
+a             : source.python
+              : source.python
++             : keyword.operator.arithmetic.python, source.python
+              : source.python
+b             : source.python
+              : source.python
++             : keyword.operator.arithmetic.python, source.python
+              : source.python
+c             : source.python
+)             : punctuation.parenthesis.end.python, source.python

From 5b5f388fc46e45dff7e48edc90242c7f578d8705 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@edgedb.com>
Date: Fri, 31 Jul 2020 06:22:53 -0400
Subject: [PATCH 64/65] Make raw f-strings consistent.

Any f-string allows variable interpolation, that includes a raw
f-string. Make all raw prefixes (`r` or `R`) behave the same way in
combination with `f` prefix.

Fixes #186
---
 grammars/MagicPython.cson              |  910 +-----------
 grammars/MagicPython.tmLanguage        | 1788 +-----------------------
 grammars/src/MagicPython.syntax.yaml   |   80 --
 grammars/src/pyfstring.inc.syntax.yaml |    2 +-
 misc/example.py                        |    2 +
 test/atom-spec/python-spec.js          |  744 +++++-----
 test/fstrings/empty2.py                |   36 +-
 test/fstrings/fraw1.py                 |   40 +
 test/fstrings/fraw2.py                 |   36 +
 test/fstrings/fraw3.py                 |   36 +
 test/fstrings/fraw4.py                 |   45 +
 test/fstrings/prefixes2.py             |   24 +-
 test/fstrings/prefixes3.py             |   24 +-
 test/regexp/fregexp1.py                |   56 -
 test/regexp/fregexp2.py                |   28 -
 test/regexp/fregexp3.py                |   28 -
 test/regexp/fregexp4.py                |   36 -
 test/regexp/fregexp5.py                |   26 -
 test/regexp/fregexp6.py                |   39 -
 19 files changed, 546 insertions(+), 3434 deletions(-)
 create mode 100644 test/fstrings/fraw1.py
 create mode 100644 test/fstrings/fraw2.py
 create mode 100644 test/fstrings/fraw3.py
 create mode 100644 test/fstrings/fraw4.py
 delete mode 100644 test/regexp/fregexp1.py
 delete mode 100644 test/regexp/fregexp2.py
 delete mode 100644 test/regexp/fregexp3.py
 delete mode 100644 test/regexp/fregexp4.py
 delete mode 100644 test/regexp/fregexp5.py
 delete mode 100644 test/regexp/fregexp6.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index b137f776..afb32a6d 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -785,18 +785,6 @@ repository:
       {
         include: "#regexp-double-one-line"
       }
-      {
-        include: "#fregexp-single-three-line"
-      }
-      {
-        include: "#fregexp-double-three-line"
-      }
-      {
-        include: "#fregexp-single-one-line"
-      }
-      {
-        include: "#fregexp-double-one-line"
-      }
     ]
   string:
     patterns: [
@@ -3334,900 +3322,6 @@ repository:
         include: "#double-three-regexp-expression"
       }
     ]
-  "single-one-fregexp-expression":
-    patterns: [
-      {
-        include: "#fregexp-base-expression"
-      }
-      {
-        include: "#single-one-regexp-character-set"
-      }
-      {
-        include: "#single-one-regexp-comments"
-      }
-      {
-        include: "#regexp-flags"
-      }
-      {
-        include: "#single-one-regexp-named-group"
-      }
-      {
-        include: "#regexp-backreference"
-      }
-      {
-        include: "#single-one-fregexp-lookahead"
-      }
-      {
-        include: "#single-one-fregexp-lookahead-negative"
-      }
-      {
-        include: "#single-one-fregexp-lookbehind"
-      }
-      {
-        include: "#single-one-fregexp-lookbehind-negative"
-      }
-      {
-        include: "#single-one-fregexp-conditional"
-      }
-      {
-        include: "#single-one-fregexp-parentheses-non-capturing"
-      }
-      {
-        include: "#single-one-fregexp-parentheses"
-      }
-    ]
-  "single-one-fregexp-named-group":
-    name: "meta.named.regexp"
-    begin: '''
-      (?x)
-        (\\()  (\\?P <\\w+(?:\\s+[[:alnum:]]+)?>)
-      
-    '''
-    end: "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "1":
-        name: "punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "entity.name.tag.named.group.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-one-fregexp-expression"
-      }
-    ]
-  "single-one-fregexp-lookahead":
-    begin: "(\\()\\?="
-    end: "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookahead.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookahead.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-one-fregexp-expression"
-      }
-    ]
-  "single-one-fregexp-lookahead-negative":
-    begin: "(\\()\\?!"
-    end: "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookahead.negative.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookahead.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-one-fregexp-expression"
-      }
-    ]
-  "single-one-fregexp-lookbehind":
-    begin: "(\\()\\?<="
-    end: "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookbehind.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookbehind.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-one-fregexp-expression"
-      }
-    ]
-  "single-one-fregexp-lookbehind-negative":
-    begin: "(\\()\\?<!"
-    end: "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookbehind.negative.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookbehind.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-one-fregexp-expression"
-      }
-    ]
-  "single-one-fregexp-conditional":
-    begin: "(\\()\\?\\((\\w+(?:\\s+[[:alnum:]]+)?|\\d+)\\)"
-    end: "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.conditional.regexp"
-      "1":
-        name: "punctuation.parenthesis.conditional.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-one-fregexp-expression"
-      }
-    ]
-  "single-one-fregexp-parentheses-non-capturing":
-    begin: "\\(\\?:"
-    end: "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-one-fregexp-expression"
-      }
-    ]
-  "single-one-fregexp-parentheses":
-    begin: "\\("
-    end: "(\\)|(?=\\'))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-one-fregexp-expression"
-      }
-    ]
-  "single-three-fregexp-expression":
-    patterns: [
-      {
-        include: "#fregexp-base-expression"
-      }
-      {
-        include: "#single-three-regexp-character-set"
-      }
-      {
-        include: "#single-three-regexp-comments"
-      }
-      {
-        include: "#regexp-flags"
-      }
-      {
-        include: "#single-three-regexp-named-group"
-      }
-      {
-        include: "#regexp-backreference"
-      }
-      {
-        include: "#single-three-fregexp-lookahead"
-      }
-      {
-        include: "#single-three-fregexp-lookahead-negative"
-      }
-      {
-        include: "#single-three-fregexp-lookbehind"
-      }
-      {
-        include: "#single-three-fregexp-lookbehind-negative"
-      }
-      {
-        include: "#single-three-fregexp-conditional"
-      }
-      {
-        include: "#single-three-fregexp-parentheses-non-capturing"
-      }
-      {
-        include: "#single-three-fregexp-parentheses"
-      }
-      {
-        include: "#comments-string-single-three"
-      }
-    ]
-  "single-three-fregexp-named-group":
-    name: "meta.named.regexp"
-    begin: '''
-      (?x)
-        (\\()  (\\?P <\\w+(?:\\s+[[:alnum:]]+)?>)
-      
-    '''
-    end: "(\\)|(?=\\'\\'\\'))"
-    beginCaptures:
-      "1":
-        name: "punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "entity.name.tag.named.group.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-single-three"
-      }
-    ]
-  "single-three-fregexp-lookahead":
-    begin: "(\\()\\?="
-    end: "(\\)|(?=\\'\\'\\'))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookahead.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookahead.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-single-three"
-      }
-    ]
-  "single-three-fregexp-lookahead-negative":
-    begin: "(\\()\\?!"
-    end: "(\\)|(?=\\'\\'\\'))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookahead.negative.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookahead.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-single-three"
-      }
-    ]
-  "single-three-fregexp-lookbehind":
-    begin: "(\\()\\?<="
-    end: "(\\)|(?=\\'\\'\\'))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookbehind.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookbehind.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-single-three"
-      }
-    ]
-  "single-three-fregexp-lookbehind-negative":
-    begin: "(\\()\\?<!"
-    end: "(\\)|(?=\\'\\'\\'))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookbehind.negative.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookbehind.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-single-three"
-      }
-    ]
-  "single-three-fregexp-conditional":
-    begin: "(\\()\\?\\((\\w+(?:\\s+[[:alnum:]]+)?|\\d+)\\)"
-    end: "(\\)|(?=\\'\\'\\'))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.conditional.regexp"
-      "1":
-        name: "punctuation.parenthesis.conditional.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-single-three"
-      }
-    ]
-  "single-three-fregexp-parentheses-non-capturing":
-    begin: "\\(\\?:"
-    end: "(\\)|(?=\\'\\'\\'))"
-    beginCaptures:
-      "0":
-        name: "punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-single-three"
-      }
-    ]
-  "single-three-fregexp-parentheses":
-    begin: "\\("
-    end: "(\\)|(?=\\'\\'\\'))"
-    beginCaptures:
-      "0":
-        name: "punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-single-three"
-      }
-    ]
-  "double-one-fregexp-expression":
-    patterns: [
-      {
-        include: "#fregexp-base-expression"
-      }
-      {
-        include: "#double-one-regexp-character-set"
-      }
-      {
-        include: "#double-one-regexp-comments"
-      }
-      {
-        include: "#regexp-flags"
-      }
-      {
-        include: "#double-one-regexp-named-group"
-      }
-      {
-        include: "#regexp-backreference"
-      }
-      {
-        include: "#double-one-fregexp-lookahead"
-      }
-      {
-        include: "#double-one-fregexp-lookahead-negative"
-      }
-      {
-        include: "#double-one-fregexp-lookbehind"
-      }
-      {
-        include: "#double-one-fregexp-lookbehind-negative"
-      }
-      {
-        include: "#double-one-fregexp-conditional"
-      }
-      {
-        include: "#double-one-fregexp-parentheses-non-capturing"
-      }
-      {
-        include: "#double-one-fregexp-parentheses"
-      }
-    ]
-  "double-one-fregexp-named-group":
-    name: "meta.named.regexp"
-    begin: '''
-      (?x)
-        (\\()  (\\?P <\\w+(?:\\s+[[:alnum:]]+)?>)
-      
-    '''
-    end: "(\\)|(?=\"))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "1":
-        name: "punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "entity.name.tag.named.group.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-one-fregexp-expression"
-      }
-    ]
-  "double-one-fregexp-lookahead":
-    begin: "(\\()\\?="
-    end: "(\\)|(?=\"))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookahead.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookahead.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-one-fregexp-expression"
-      }
-    ]
-  "double-one-fregexp-lookahead-negative":
-    begin: "(\\()\\?!"
-    end: "(\\)|(?=\"))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookahead.negative.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookahead.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-one-fregexp-expression"
-      }
-    ]
-  "double-one-fregexp-lookbehind":
-    begin: "(\\()\\?<="
-    end: "(\\)|(?=\"))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookbehind.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookbehind.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-one-fregexp-expression"
-      }
-    ]
-  "double-one-fregexp-lookbehind-negative":
-    begin: "(\\()\\?<!"
-    end: "(\\)|(?=\"))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookbehind.negative.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookbehind.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-one-fregexp-expression"
-      }
-    ]
-  "double-one-fregexp-conditional":
-    begin: "(\\()\\?\\((\\w+(?:\\s+[[:alnum:]]+)?|\\d+)\\)"
-    end: "(\\)|(?=\"))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.conditional.regexp"
-      "1":
-        name: "punctuation.parenthesis.conditional.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-one-fregexp-expression"
-      }
-    ]
-  "double-one-fregexp-parentheses-non-capturing":
-    begin: "\\(\\?:"
-    end: "(\\)|(?=\"))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-one-fregexp-expression"
-      }
-    ]
-  "double-one-fregexp-parentheses":
-    begin: "\\("
-    end: "(\\)|(?=\"))|((?=(?<!\\\\)\\n))"
-    beginCaptures:
-      "0":
-        name: "punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-one-fregexp-expression"
-      }
-    ]
-  "double-three-fregexp-expression":
-    patterns: [
-      {
-        include: "#fregexp-base-expression"
-      }
-      {
-        include: "#double-three-regexp-character-set"
-      }
-      {
-        include: "#double-three-regexp-comments"
-      }
-      {
-        include: "#regexp-flags"
-      }
-      {
-        include: "#double-three-regexp-named-group"
-      }
-      {
-        include: "#regexp-backreference"
-      }
-      {
-        include: "#double-three-fregexp-lookahead"
-      }
-      {
-        include: "#double-three-fregexp-lookahead-negative"
-      }
-      {
-        include: "#double-three-fregexp-lookbehind"
-      }
-      {
-        include: "#double-three-fregexp-lookbehind-negative"
-      }
-      {
-        include: "#double-three-fregexp-conditional"
-      }
-      {
-        include: "#double-three-fregexp-parentheses-non-capturing"
-      }
-      {
-        include: "#double-three-fregexp-parentheses"
-      }
-      {
-        include: "#comments-string-double-three"
-      }
-    ]
-  "double-three-fregexp-named-group":
-    name: "meta.named.regexp"
-    begin: '''
-      (?x)
-        (\\()  (\\?P <\\w+(?:\\s+[[:alnum:]]+)?>)
-      
-    '''
-    end: "(\\)|(?=\"\"\"))"
-    beginCaptures:
-      "1":
-        name: "punctuation.parenthesis.named.begin.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "entity.name.tag.named.group.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.named.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-double-three"
-      }
-    ]
-  "double-three-fregexp-lookahead":
-    begin: "(\\()\\?="
-    end: "(\\)|(?=\"\"\"))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookahead.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookahead.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-double-three"
-      }
-    ]
-  "double-three-fregexp-lookahead-negative":
-    begin: "(\\()\\?!"
-    end: "(\\)|(?=\"\"\"))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookahead.negative.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookahead.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookahead.end.regexp keyword.operator.lookahead.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-double-three"
-      }
-    ]
-  "double-three-fregexp-lookbehind":
-    begin: "(\\()\\?<="
-    end: "(\\)|(?=\"\"\"))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookbehind.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookbehind.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-double-three"
-      }
-    ]
-  "double-three-fregexp-lookbehind-negative":
-    begin: "(\\()\\?<!"
-    end: "(\\)|(?=\"\"\"))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.lookbehind.negative.regexp"
-      "1":
-        name: "punctuation.parenthesis.lookbehind.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.lookbehind.end.regexp keyword.operator.lookbehind.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-double-three"
-      }
-    ]
-  "double-three-fregexp-conditional":
-    begin: "(\\()\\?\\((\\w+(?:\\s+[[:alnum:]]+)?|\\d+)\\)"
-    end: "(\\)|(?=\"\"\"))"
-    beginCaptures:
-      "0":
-        name: "keyword.operator.conditional.regexp"
-      "1":
-        name: "punctuation.parenthesis.conditional.begin.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.conditional.end.regexp keyword.operator.conditional.negative.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-double-three"
-      }
-    ]
-  "double-three-fregexp-parentheses-non-capturing":
-    begin: "\\(\\?:"
-    end: "(\\)|(?=\"\"\"))"
-    beginCaptures:
-      "0":
-        name: "punctuation.parenthesis.non-capturing.begin.regexp support.other.parenthesis.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.non-capturing.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-double-three"
-      }
-    ]
-  "double-three-fregexp-parentheses":
-    begin: "\\("
-    end: "(\\)|(?=\"\"\"))"
-    beginCaptures:
-      "0":
-        name: "punctuation.parenthesis.begin.regexp support.other.parenthesis.regexp"
-    endCaptures:
-      "1":
-        name: "punctuation.parenthesis.end.regexp support.other.parenthesis.regexp"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-three-fregexp-expression"
-      }
-      {
-        include: "#comments-string-double-three"
-      }
-    ]
-  "fregexp-single-one-line":
-    name: "string.regexp.quoted.single.python string.interpolated.python"
-    begin: "\\b(([uU]r)|([fF]r)|(r[fF]?))(\\')"
-    end: "(\\')|(?<!\\\\)(\\n)"
-    beginCaptures:
-      "2":
-        name: "invalid.deprecated.prefix.python"
-      "3":
-        name: "storage.type.string.python"
-      "4":
-        name: "storage.type.string.python"
-      "5":
-        name: "punctuation.definition.string.begin.python"
-    endCaptures:
-      "1":
-        name: "punctuation.definition.string.end.python"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-one-fregexp-expression"
-      }
-    ]
-  "fregexp-single-three-line":
-    name: "string.regexp.quoted.multi.python string.interpolated.python"
-    begin: "\\b(([uU]r)|([fF]r)|(r[fF]?))(\\'\\'\\')"
-    end: "(\\'\\'\\')"
-    beginCaptures:
-      "2":
-        name: "invalid.deprecated.prefix.python"
-      "3":
-        name: "storage.type.string.python"
-      "4":
-        name: "storage.type.string.python"
-      "5":
-        name: "punctuation.definition.string.begin.python"
-    endCaptures:
-      "1":
-        name: "punctuation.definition.string.end.python"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#single-three-fregexp-expression"
-      }
-    ]
-  "fregexp-double-one-line":
-    name: "string.regexp.quoted.single.python string.interpolated.python"
-    begin: "\\b(([uU]r)|([fF]r)|(r[fF]?))(\")"
-    end: "(\")|(?<!\\\\)(\\n)"
-    beginCaptures:
-      "2":
-        name: "invalid.deprecated.prefix.python"
-      "3":
-        name: "storage.type.string.python"
-      "4":
-        name: "storage.type.string.python"
-      "5":
-        name: "punctuation.definition.string.begin.python"
-    endCaptures:
-      "1":
-        name: "punctuation.definition.string.end.python"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-one-fregexp-expression"
-      }
-    ]
-  "fregexp-double-three-line":
-    name: "string.regexp.quoted.multi.python string.interpolated.python"
-    begin: "\\b(([uU]r)|([fF]r)|(r[fF]?))(\"\"\")"
-    end: "(\"\"\")"
-    beginCaptures:
-      "2":
-        name: "invalid.deprecated.prefix.python"
-      "3":
-        name: "storage.type.string.python"
-      "4":
-        name: "storage.type.string.python"
-      "5":
-        name: "punctuation.definition.string.begin.python"
-    endCaptures:
-      "1":
-        name: "punctuation.definition.string.end.python"
-      "2":
-        name: "invalid.illegal.newline.python"
-    patterns: [
-      {
-        include: "#double-three-fregexp-expression"
-      }
-    ]
   "string-raw-quoted-single-line":
     name: "string.quoted.raw.single.python"
     begin: "\\b(([uU]R)|(R))((['\"]))"
@@ -4638,7 +3732,7 @@ repository:
     ]
   "fstring-raw-quoted-single-line":
     name: "meta.fstring.python"
-    begin: "(\\b(?:[R][fF]|[fF][R]))((['\"]))"
+    begin: "(\\b(?:[rR][fF]|[fF][rR]))((['\"]))"
     end: "(\\2)|((?<!\\\\)\\n)"
     beginCaptures:
       "1":
@@ -4866,7 +3960,7 @@ repository:
     ]
   "fstring-raw-quoted-multi-line":
     name: "meta.fstring.python"
-    begin: "(\\b(?:[R][fF]|[fF][R]))('''|\"\"\")"
+    begin: "(\\b(?:[rR][fF]|[fF][rR]))('''|\"\"\")"
     end: "(\\2)"
     beginCaptures:
       "1":
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index a4f973df..a3f1bd2b 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -1197,22 +1197,6 @@ E.g. "arr[idx](args)"
             <key>include</key>
             <string>#regexp-double-one-line</string>
           </dict>
-          <dict>
-            <key>include</key>
-            <string>#fregexp-single-three-line</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#fregexp-double-three-line</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#fregexp-single-one-line</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#fregexp-double-one-line</string>
-          </dict>
         </array>
       </dict>
       <key>string</key>
@@ -5646,1774 +5630,6 @@ indirectly through syntactic constructs
           </dict>
         </array>
       </dict>
-      <key>single-one-fregexp-expression</key>
-      <dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#fregexp-base-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-one-regexp-character-set</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-one-regexp-comments</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#regexp-flags</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-one-regexp-named-group</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#regexp-backreference</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-lookahead</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-lookahead-negative</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-lookbehind</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-lookbehind-negative</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-conditional</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-parentheses-non-capturing</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-parentheses</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-one-fregexp-named-group</key>
-      <dict>
-        <key>name</key>
-        <string>meta.named.regexp</string>
-        <key>begin</key>
-        <string>(?x)
-  (\()  (\?P &lt;\w+(?:\s+[[:alnum:]]+)?&gt;)
-</string>
-        <key>end</key>
-        <string>(\)|(?=\'))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>entity.name.tag.named.group.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-one-fregexp-lookahead</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?=</string>
-        <key>end</key>
-        <string>(\)|(?=\'))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookahead.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-one-fregexp-lookahead-negative</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?!</string>
-        <key>end</key>
-        <string>(\)|(?=\'))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.negative.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookahead.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-one-fregexp-lookbehind</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?&lt;=</string>
-        <key>end</key>
-        <string>(\)|(?=\'))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-one-fregexp-lookbehind-negative</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?&lt;!</string>
-        <key>end</key>
-        <string>(\)|(?=\'))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.negative.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-one-fregexp-conditional</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?\((\w+(?:\s+[[:alnum:]]+)?|\d+)\)</string>
-        <key>end</key>
-        <string>(\)|(?=\'))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.conditional.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.conditional.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-one-fregexp-parentheses-non-capturing</key>
-      <dict>
-        <key>begin</key>
-        <string>\(\?:</string>
-        <key>end</key>
-        <string>(\)|(?=\'))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-one-fregexp-parentheses</key>
-      <dict>
-        <key>begin</key>
-        <string>\(</string>
-        <key>end</key>
-        <string>(\)|(?=\'))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-three-fregexp-expression</key>
-      <dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#fregexp-base-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-three-regexp-character-set</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-three-regexp-comments</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#regexp-flags</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-three-regexp-named-group</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#regexp-backreference</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-lookahead</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-lookahead-negative</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-lookbehind</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-lookbehind-negative</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-conditional</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-parentheses-non-capturing</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-parentheses</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-single-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-three-fregexp-named-group</key>
-      <dict>
-        <key>name</key>
-        <string>meta.named.regexp</string>
-        <key>begin</key>
-        <string>(?x)
-  (\()  (\?P &lt;\w+(?:\s+[[:alnum:]]+)?&gt;)
-</string>
-        <key>end</key>
-        <string>(\)|(?=\'\'\'))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>entity.name.tag.named.group.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-single-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-three-fregexp-lookahead</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?=</string>
-        <key>end</key>
-        <string>(\)|(?=\'\'\'))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookahead.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-single-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-three-fregexp-lookahead-negative</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?!</string>
-        <key>end</key>
-        <string>(\)|(?=\'\'\'))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.negative.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookahead.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-single-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-three-fregexp-lookbehind</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?&lt;=</string>
-        <key>end</key>
-        <string>(\)|(?=\'\'\'))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-single-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-three-fregexp-lookbehind-negative</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?&lt;!</string>
-        <key>end</key>
-        <string>(\)|(?=\'\'\'))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.negative.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-single-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-three-fregexp-conditional</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?\((\w+(?:\s+[[:alnum:]]+)?|\d+)\)</string>
-        <key>end</key>
-        <string>(\)|(?=\'\'\'))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.conditional.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.conditional.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-single-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-three-fregexp-parentheses-non-capturing</key>
-      <dict>
-        <key>begin</key>
-        <string>\(\?:</string>
-        <key>end</key>
-        <string>(\)|(?=\'\'\'))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-single-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>single-three-fregexp-parentheses</key>
-      <dict>
-        <key>begin</key>
-        <string>\(</string>
-        <key>end</key>
-        <string>(\)|(?=\'\'\'))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-single-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-one-fregexp-expression</key>
-      <dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#fregexp-base-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-one-regexp-character-set</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-one-regexp-comments</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#regexp-flags</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-one-regexp-named-group</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#regexp-backreference</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-lookahead</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-lookahead-negative</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-lookbehind</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-lookbehind-negative</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-conditional</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-parentheses-non-capturing</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-parentheses</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-one-fregexp-named-group</key>
-      <dict>
-        <key>name</key>
-        <string>meta.named.regexp</string>
-        <key>begin</key>
-        <string>(?x)
-  (\()  (\?P &lt;\w+(?:\s+[[:alnum:]]+)?&gt;)
-</string>
-        <key>end</key>
-        <string>(\)|(?="))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>entity.name.tag.named.group.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-one-fregexp-lookahead</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?=</string>
-        <key>end</key>
-        <string>(\)|(?="))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookahead.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-one-fregexp-lookahead-negative</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?!</string>
-        <key>end</key>
-        <string>(\)|(?="))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.negative.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookahead.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-one-fregexp-lookbehind</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?&lt;=</string>
-        <key>end</key>
-        <string>(\)|(?="))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-one-fregexp-lookbehind-negative</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?&lt;!</string>
-        <key>end</key>
-        <string>(\)|(?="))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.negative.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-one-fregexp-conditional</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?\((\w+(?:\s+[[:alnum:]]+)?|\d+)\)</string>
-        <key>end</key>
-        <string>(\)|(?="))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.conditional.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.conditional.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-one-fregexp-parentheses-non-capturing</key>
-      <dict>
-        <key>begin</key>
-        <string>\(\?:</string>
-        <key>end</key>
-        <string>(\)|(?="))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-one-fregexp-parentheses</key>
-      <dict>
-        <key>begin</key>
-        <string>\(</string>
-        <key>end</key>
-        <string>(\)|(?="))|((?=(?&lt;!\\)\n))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-three-fregexp-expression</key>
-      <dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#fregexp-base-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-three-regexp-character-set</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-three-regexp-comments</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#regexp-flags</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-three-regexp-named-group</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#regexp-backreference</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-lookahead</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-lookahead-negative</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-lookbehind</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-lookbehind-negative</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-conditional</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-parentheses-non-capturing</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-parentheses</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-double-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-three-fregexp-named-group</key>
-      <dict>
-        <key>name</key>
-        <string>meta.named.regexp</string>
-        <key>begin</key>
-        <string>(?x)
-  (\()  (\?P &lt;\w+(?:\s+[[:alnum:]]+)?&gt;)
-</string>
-        <key>end</key>
-        <string>(\)|(?="""))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>entity.name.tag.named.group.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-double-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-three-fregexp-lookahead</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?=</string>
-        <key>end</key>
-        <string>(\)|(?="""))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookahead.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-double-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-three-fregexp-lookahead-negative</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?!</string>
-        <key>end</key>
-        <string>(\)|(?="""))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.negative.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookahead.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-double-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-three-fregexp-lookbehind</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?&lt;=</string>
-        <key>end</key>
-        <string>(\)|(?="""))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-double-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-three-fregexp-lookbehind-negative</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?&lt;!</string>
-        <key>end</key>
-        <string>(\)|(?="""))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.negative.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.lookbehind.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-double-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-three-fregexp-conditional</key>
-      <dict>
-        <key>begin</key>
-        <string>(\()\?\((\w+(?:\s+[[:alnum:]]+)?|\d+)\)</string>
-        <key>end</key>
-        <string>(\)|(?="""))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.conditional.regexp</string>
-          </dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.parenthesis.conditional.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-double-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-three-fregexp-parentheses-non-capturing</key>
-      <dict>
-        <key>begin</key>
-        <string>\(\?:</string>
-        <key>end</key>
-        <string>(\)|(?="""))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-double-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>double-three-fregexp-parentheses</key>
-      <dict>
-        <key>begin</key>
-        <string>\(</string>
-        <key>end</key>
-        <string>(\)|(?="""))</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>0</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>support.other.parenthesis.regexp punctuation.parenthesis.end.regexp</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-expression</string>
-          </dict>
-          <dict>
-            <key>include</key>
-            <string>#comments-string-double-three</string>
-          </dict>
-        </array>
-      </dict>
-      <key>fregexp-single-one-line</key>
-      <dict>
-        <key>name</key>
-        <string>string.interpolated.python string.regexp.quoted.single.python</string>
-        <key>begin</key>
-        <string>\b(([uU]r)|([fF]r)|(r[fF]?))(\')</string>
-        <key>end</key>
-        <string>(\')|(?&lt;!\\)(\n)</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.deprecated.prefix.python</string>
-          </dict>
-          <key>3</key>
-          <dict>
-            <key>name</key>
-            <string>storage.type.string.python</string>
-          </dict>
-          <key>4</key>
-          <dict>
-            <key>name</key>
-            <string>storage.type.string.python</string>
-          </dict>
-          <key>5</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.definition.string.begin.python</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.definition.string.end.python</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>fregexp-single-three-line</key>
-      <dict>
-        <key>name</key>
-        <string>string.interpolated.python string.regexp.quoted.multi.python</string>
-        <key>begin</key>
-        <string>\b(([uU]r)|([fF]r)|(r[fF]?))(\'\'\')</string>
-        <key>end</key>
-        <string>(\'\'\')</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.deprecated.prefix.python</string>
-          </dict>
-          <key>3</key>
-          <dict>
-            <key>name</key>
-            <string>storage.type.string.python</string>
-          </dict>
-          <key>4</key>
-          <dict>
-            <key>name</key>
-            <string>storage.type.string.python</string>
-          </dict>
-          <key>5</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.definition.string.begin.python</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.definition.string.end.python</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#single-three-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>fregexp-double-one-line</key>
-      <dict>
-        <key>name</key>
-        <string>string.interpolated.python string.regexp.quoted.single.python</string>
-        <key>begin</key>
-        <string>\b(([uU]r)|([fF]r)|(r[fF]?))(")</string>
-        <key>end</key>
-        <string>(")|(?&lt;!\\)(\n)</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.deprecated.prefix.python</string>
-          </dict>
-          <key>3</key>
-          <dict>
-            <key>name</key>
-            <string>storage.type.string.python</string>
-          </dict>
-          <key>4</key>
-          <dict>
-            <key>name</key>
-            <string>storage.type.string.python</string>
-          </dict>
-          <key>5</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.definition.string.begin.python</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.definition.string.end.python</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-one-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
-      <key>fregexp-double-three-line</key>
-      <dict>
-        <key>name</key>
-        <string>string.interpolated.python string.regexp.quoted.multi.python</string>
-        <key>begin</key>
-        <string>\b(([uU]r)|([fF]r)|(r[fF]?))(""")</string>
-        <key>end</key>
-        <string>(""")</string>
-        <key>beginCaptures</key>
-        <dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.deprecated.prefix.python</string>
-          </dict>
-          <key>3</key>
-          <dict>
-            <key>name</key>
-            <string>storage.type.string.python</string>
-          </dict>
-          <key>4</key>
-          <dict>
-            <key>name</key>
-            <string>storage.type.string.python</string>
-          </dict>
-          <key>5</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.definition.string.begin.python</string>
-          </dict>
-        </dict>
-        <key>endCaptures</key>
-        <dict>
-          <key>1</key>
-          <dict>
-            <key>name</key>
-            <string>punctuation.definition.string.end.python</string>
-          </dict>
-          <key>2</key>
-          <dict>
-            <key>name</key>
-            <string>invalid.illegal.newline.python</string>
-          </dict>
-        </dict>
-        <key>patterns</key>
-        <array>
-          <dict>
-            <key>include</key>
-            <string>#double-three-fregexp-expression</string>
-          </dict>
-        </array>
-      </dict>
       <key>string-raw-quoted-single-line</key>
       <dict>
         <key>name</key>
@@ -8137,7 +6353,7 @@ indirectly through syntactic constructs
         <key>name</key>
         <string>meta.fstring.python</string>
         <key>begin</key>
-        <string>(\b(?:[R][fF]|[fF][R]))((['"]))</string>
+        <string>(\b(?:[rR][fF]|[fF][rR]))((['"]))</string>
         <key>end</key>
         <string>(\2)|((?&lt;!\\)\n)</string>
         <key>beginCaptures</key>
@@ -8515,7 +6731,7 @@ indirectly through syntactic constructs
         <key>name</key>
         <string>meta.fstring.python</string>
         <key>begin</key>
-        <string>(\b(?:[R][fF]|[fF][R]))('''|""")</string>
+        <string>(\b(?:[rR][fF]|[fF][rR]))('''|""")</string>
         <key>end</key>
         <string>(\2)</string>
         <key>beginCaptures</key>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index 83948dc1..bd740829 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -103,82 +103,6 @@ repository:
         bquote: '(""")'
         equote: '(""")'
 
-    - file: 'regexp.inc.syntax.yaml'
-      vars:
-        prefix: 'single-one-'
-        basename: 'fregexp'
-        marker: "|(?=\\')"
-        nested: ''
-        guard: "|((?=(?<!\\\\)\\n))"
-
-    - file: 'regexp.inc.syntax.yaml'
-      vars:
-        prefix: 'single-three-'
-        basename: 'fregexp'
-        marker: "|(?=\\'\\'\\')"
-        nested: "- include: '#comments-string-single-three'"
-        guard: ""
-
-    - file: 'regexp.inc.syntax.yaml'
-      vars:
-        prefix: 'double-one-'
-        basename: 'fregexp'
-        marker: '|(?=")'
-        nested: ''
-        guard: "|((?=(?<!\\\\)\\n))"
-
-    - file: 'regexp.inc.syntax.yaml'
-      vars:
-        prefix: 'double-three-'
-        basename: 'fregexp'
-        marker: '|(?=""")'
-        nested: "- include: '#comments-string-double-three'"
-        guard: ""
-
-    - file: 'regexp.wrapper.syntax.yaml'
-      vars:
-        scopename: string.regexp.quoted.single.python
-                   string.interpolated.python
-        prefix: 'single-one-'
-        basename: 'fregexp'
-        nested: ''
-        modifier: '[fF]'
-        bquote: "(\\')"
-        equote: "(\\')|(?<!\\\\)(\\n)"
-
-    - file: 'regexp.wrapper.syntax.yaml'
-      vars:
-        scopename: string.regexp.quoted.multi.python
-                   string.interpolated.python
-        prefix: 'single-three-'
-        basename: 'fregexp'
-        nested: "- include: '#comments-string-single-three'"
-        modifier: '[fF]'
-        bquote: "(\\'\\'\\')"
-        equote: "(\\'\\'\\')"
-
-    - file: 'regexp.wrapper.syntax.yaml'
-      vars:
-        scopename: string.regexp.quoted.single.python
-                   string.interpolated.python
-        prefix: 'double-one-'
-        basename: 'fregexp'
-        nested: ''
-        modifier: '[fF]'
-        bquote: '(")'
-        equote: '(")|(?<!\\)(\n)'
-
-    - file: 'regexp.wrapper.syntax.yaml'
-      vars:
-        scopename: string.regexp.quoted.multi.python
-                   string.interpolated.python
-        prefix: 'double-three-'
-        basename: 'fregexp'
-        nested: "- include: '#comments-string-double-three'"
-        modifier: '[fF]'
-        bquote: '(""")'
-        equote: '(""")'
-
     - file: 'pystring.inc.syntax.yaml'
       vars:
         line: single
@@ -700,10 +624,6 @@ repository:
       - include: '#regexp-double-three-line'
       - include: '#regexp-single-one-line'
       - include: '#regexp-double-one-line'
-      - include: '#fregexp-single-three-line'
-      - include: '#fregexp-double-three-line'
-      - include: '#fregexp-single-one-line'
-      - include: '#fregexp-double-one-line'
 
   string:
     patterns:
diff --git a/grammars/src/pyfstring.inc.syntax.yaml b/grammars/src/pyfstring.inc.syntax.yaml
index e605f17c..0a23fc24 100644
--- a/grammars/src/pyfstring.inc.syntax.yaml
+++ b/grammars/src/pyfstring.inc.syntax.yaml
@@ -51,7 +51,7 @@ fstring-normf-quoted-${line}-line:
 
 fstring-raw-quoted-${line}-line:
   name: meta.fstring.python
-  begin: (\b(?:[R][fF]|[fF][R]))(${marker})
+  begin: (\b(?:[rR][fF]|[fF][rR]))(${marker})
   end: (\2)${guard}
   beginCaptures:
     '1': {name: storage.type.string.python
diff --git a/misc/example.py b/misc/example.py
index e6ea7ad0..718f3074 100644
--- a/misc/example.py
+++ b/misc/example.py
@@ -22,6 +22,8 @@ async def coroutine(db:aio_db.DatabaseConnection) -> List[str]:
         async with db.transaction():
             result = await db.query(...)
             print(f'Result: {result!r} {a=} {b=!r}')
+            print(Rf'data: {c=}')
+            print(rf'data: {c=}')
 
     mapping = None     # type: Dict[int, Any] # PEP 484
 
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index da7d08c1..cf00b257 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -6610,39 +6610,313 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("rf\"{} {  }\"\nrf\"\"\"{}\n{  }\n\"\"\"")
       expect(tokens[0][0].value).toBe("rf");
-      expect(tokens[0][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
       expect(tokens[0][1].value).toBe("\"");
-      expect(tokens[0][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
       expect(tokens[0][2].value).toBe("{");
-      expect(tokens[0][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][3].value).toBe("}");
-      expect(tokens[0][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][4].value).toBe(" ");
-      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
       expect(tokens[0][5].value).toBe("{");
-      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][6].value).toBe("  ");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","invalid.illegal.brace.python"]);
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.brace.python"]);
       expect(tokens[0][7].value).toBe("}");
-      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[0][8].value).toBe("\"");
-      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
       expect(tokens[1][0].value).toBe("rf");
-      expect(tokens[1][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.multi.python string.interpolated.python"]);
       expect(tokens[1][1].value).toBe("\"\"\"");
-      expect(tokens[1][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python punctuation.definition.string.begin.python"]);
       expect(tokens[1][2].value).toBe("{");
-      expect(tokens[1][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[1][3].value).toBe("}");
-      expect(tokens[1][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][4].value).toBe("");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python"]);
       expect(tokens[2][0].value).toBe("{");
-      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
       expect(tokens[2][1].value).toBe("  ");
-      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","invalid.illegal.brace.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","invalid.illegal.brace.python"]);
       expect(tokens[2][2].value).toBe("}");
-      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][3].value).toBe("");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python"]);
       expect(tokens[3][0].value).toBe("\"\"\"");
-      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/fraw1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = fr'[a-z]'\na = Fr'[a-z]'\na = rf'[a-z]'\na = rF'[a-z]'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("fr");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("[a-z]");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[0][7].value).toBe("'");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("Fr");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("[a-z]");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[1][7].value).toBe("'");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("rf");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("[a-z]");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[2][7].value).toBe("'");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("a");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe(" ");
+      expect(tokens[3][1].scopes).toEqual(["source.python"]);
+      expect(tokens[3][2].value).toBe("=");
+      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][3].value).toBe(" ");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe("rF");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[3][5].value).toBe("'");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[3][6].value).toBe("[a-z]");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[3][7].value).toBe("'");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/fraw2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("rf'fo{{2}}'\nrf\"fo{{2}}\"\nrf'''fo{{2}}'''\nrf\"\"\"fo{{2}}\"\"\"")
+      expect(tokens[0][0].value).toBe("rf");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("fo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{{");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][4].value).toBe("2");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("}}");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][6].value).toBe("'");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("rf");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[1][1].value).toBe("\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("fo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[1][3].value).toBe("{{");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[1][4].value).toBe("2");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[1][5].value).toBe("}}");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[1][6].value).toBe("\"");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("rf");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.multi.python string.interpolated.python"]);
+      expect(tokens[2][1].value).toBe("'''");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("fo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python"]);
+      expect(tokens[2][3].value).toBe("{{");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[2][4].value).toBe("2");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python"]);
+      expect(tokens[2][5].value).toBe("}}");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[2][6].value).toBe("'''");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("rf");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.multi.python string.interpolated.python"]);
+      expect(tokens[3][1].value).toBe("\"\"\"");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe("fo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python"]);
+      expect(tokens[3][3].value).toBe("{{");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[3][4].value).toBe("2");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python"]);
+      expect(tokens[3][5].value).toBe("}}");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[3][6].value).toBe("\"\"\"");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/fraw3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("rf'fo{2}'\nrf\"fo{2}\"\nrf'''fo{2}'''\nrf\"\"\"fo{2}\"\"\"")
+      expect(tokens[0][0].value).toBe("rf");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[0][1].value).toBe("'");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][2].value).toBe("fo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][4].value).toBe("2");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][5].value).toBe("}");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].value).toBe("'");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("rf");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[1][1].value).toBe("\"");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[1][2].value).toBe("fo");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[1][3].value).toBe("{");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][4].value).toBe("2");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[1][5].value).toBe("}");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][6].value).toBe("\"");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("rf");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.multi.python string.interpolated.python"]);
+      expect(tokens[2][1].value).toBe("'''");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python punctuation.definition.string.begin.python"]);
+      expect(tokens[2][2].value).toBe("fo");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python"]);
+      expect(tokens[2][3].value).toBe("{");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][4].value).toBe("2");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[2][5].value).toBe("}");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][6].value).toBe("'''");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[3][0].value).toBe("rf");
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.multi.python string.interpolated.python"]);
+      expect(tokens[3][1].value).toBe("\"\"\"");
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python punctuation.definition.string.begin.python"]);
+      expect(tokens[3][2].value).toBe("fo");
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python"]);
+      expect(tokens[3][3].value).toBe("{");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][4].value).toBe("2");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[3][5].value).toBe("}");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][6].value).toBe("\"\"\"");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.multi.python string.interpolated.python punctuation.definition.string.end.python"]);
+    });
+
+  it("test/fstrings/fraw4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("a = rf'fo{{{2}}}'\na = rf'fo{{{bar}}}'\na = rf'fo{{2}}'")
+      expect(tokens[0][0].value).toBe("a");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("rf");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[0][5].value).toBe("'");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[0][6].value).toBe("fo");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[0][7].value).toBe("{{");
+      expect(tokens[0][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][8].value).toBe("{");
+      expect(tokens[0][8].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][9].value).toBe("2");
+      expect(tokens[0][9].scopes).toEqual(["source.python","meta.fstring.python","constant.numeric.dec.python"]);
+      expect(tokens[0][10].value).toBe("}");
+      expect(tokens[0][10].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][11].value).toBe("}}");
+      expect(tokens[0][11].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[0][12].value).toBe("'");
+      expect(tokens[0][12].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[1][0].value).toBe("a");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("rf");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[1][5].value).toBe("'");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[1][6].value).toBe("fo");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[1][7].value).toBe("{{");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[1][8].value).toBe("{");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][9].value).toBe("bar");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][10].value).toBe("}");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][11].value).toBe("}}");
+      expect(tokens[1][11].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[1][12].value).toBe("'");
+      expect(tokens[1][12].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][0].value).toBe("a");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("=");
+      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("rf");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[2][5].value).toBe("'");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
+      expect(tokens[2][6].value).toBe("fo");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[2][7].value).toBe("{{");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[2][8].value).toBe("2");
+      expect(tokens[2][8].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[2][9].value).toBe("}}");
+      expect(tokens[2][9].scopes).toEqual(["source.python","meta.fstring.python","constant.character.escape.python"]);
+      expect(tokens[2][10].value).toBe("'");
+      expect(tokens[2][10].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
     });
 
   it("test/fstrings/nested1.py", 
@@ -7084,25 +7358,33 @@ describe("Grammar Tests", function() {
       expect(tokens[1][6].value).toBe("'");
       expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
       expect(tokens[2][0].value).toBe("rf");
-      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
       expect(tokens[2][1].value).toBe("'");
-      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
       expect(tokens[2][2].value).toBe("some ");
-      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[2][3].value).toBe("{obj}");
-      expect(tokens[2][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[2][4].value).toBe("'");
-      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[2][3].value).toBe("{");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][4].value).toBe("obj");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[2][5].value).toBe("}");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[2][6].value).toBe("'");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
       expect(tokens[3][0].value).toBe("rF");
-      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[3][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
       expect(tokens[3][1].value).toBe("'");
-      expect(tokens[3][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
       expect(tokens[3][2].value).toBe("some ");
-      expect(tokens[3][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[3][3].value).toBe("{obj}");
-      expect(tokens[3][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[3][4].value).toBe("'");
-      expect(tokens[3][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[3][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[3][3].value).toBe("{");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][4].value).toBe("obj");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[3][5].value).toBe("}");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[3][6].value).toBe("'");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
       expect(tokens[4][0].value).toBe("Rf");
       expect(tokens[4][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
       expect(tokens[4][1].value).toBe("'");
@@ -7137,25 +7419,33 @@ describe("Grammar Tests", function() {
     function() {
       tokens = grammar.tokenizeLines("fr'some {obj}'\nFr'some {obj}'\nfR'some {obj}'\nFR'some {obj}'")
       expect(tokens[0][0].value).toBe("fr");
-      expect(tokens[0][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
       expect(tokens[0][1].value).toBe("'");
-      expect(tokens[0][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
       expect(tokens[0][2].value).toBe("some ");
-      expect(tokens[0][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[0][3].value).toBe("{obj}");
-      expect(tokens[0][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[0][4].value).toBe("'");
-      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[0][3].value).toBe("{");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][4].value).toBe("obj");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[0][5].value).toBe("}");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[0][6].value).toBe("'");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
       expect(tokens[1][0].value).toBe("Fr");
-      expect(tokens[1][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
       expect(tokens[1][1].value).toBe("'");
-      expect(tokens[1][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python punctuation.definition.string.begin.python"]);
       expect(tokens[1][2].value).toBe("some ");
-      expect(tokens[1][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[1][3].value).toBe("{obj}");
-      expect(tokens[1][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[1][4].value).toBe("'");
-      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python"]);
+      expect(tokens[1][3].value).toBe("{");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][4].value).toBe("obj");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[1][5].value).toBe("}");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[1][6].value).toBe("'");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.raw.single.python string.interpolated.python punctuation.definition.string.end.python"]);
       expect(tokens[2][0].value).toBe("fR");
       expect(tokens[2][0].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.raw.single.python string.interpolated.python"]);
       expect(tokens[2][1].value).toBe("'");
@@ -10724,370 +11014,6 @@ describe("Grammar Tests", function() {
       expect(tokens[0][15].scopes).toEqual(["source.python","string.regexp.quoted.multi.python","punctuation.definition.string.end.python"]);
     });
 
-  it("test/regexp/fregexp1.py", 
-    function() {
-      tokens = grammar.tokenizeLines("a = fr'[a-z]'\na = Fr'[a-z]'\na = rf'[a-z]'\na = rF'[a-z]'")
-      expect(tokens[0][0].value).toBe("a");
-      expect(tokens[0][0].scopes).toEqual(["source.python"]);
-      expect(tokens[0][1].value).toBe(" ");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
-      expect(tokens[0][2].value).toBe("=");
-      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[0][3].value).toBe(" ");
-      expect(tokens[0][3].scopes).toEqual(["source.python"]);
-      expect(tokens[0][4].value).toBe("fr");
-      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[0][5].value).toBe("'");
-      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[0][6].value).toBe("[");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
-      expect(tokens[0][7].value).toBe("a");
-      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[0][8].value).toBe("-");
-      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[0][9].value).toBe("z");
-      expect(tokens[0][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[0][10].value).toBe("]");
-      expect(tokens[0][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
-      expect(tokens[0][11].value).toBe("'");
-      expect(tokens[0][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[1][0].value).toBe("a");
-      expect(tokens[1][0].scopes).toEqual(["source.python"]);
-      expect(tokens[1][1].value).toBe(" ");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
-      expect(tokens[1][2].value).toBe("=");
-      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[1][3].value).toBe(" ");
-      expect(tokens[1][3].scopes).toEqual(["source.python"]);
-      expect(tokens[1][4].value).toBe("Fr");
-      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[1][5].value).toBe("'");
-      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[1][6].value).toBe("[");
-      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
-      expect(tokens[1][7].value).toBe("a");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[1][8].value).toBe("-");
-      expect(tokens[1][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[1][9].value).toBe("z");
-      expect(tokens[1][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[1][10].value).toBe("]");
-      expect(tokens[1][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
-      expect(tokens[1][11].value).toBe("'");
-      expect(tokens[1][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[2][0].value).toBe("a");
-      expect(tokens[2][0].scopes).toEqual(["source.python"]);
-      expect(tokens[2][1].value).toBe(" ");
-      expect(tokens[2][1].scopes).toEqual(["source.python"]);
-      expect(tokens[2][2].value).toBe("=");
-      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[2][3].value).toBe(" ");
-      expect(tokens[2][3].scopes).toEqual(["source.python"]);
-      expect(tokens[2][4].value).toBe("rf");
-      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[2][5].value).toBe("'");
-      expect(tokens[2][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[2][6].value).toBe("[");
-      expect(tokens[2][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
-      expect(tokens[2][7].value).toBe("a");
-      expect(tokens[2][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[2][8].value).toBe("-");
-      expect(tokens[2][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[2][9].value).toBe("z");
-      expect(tokens[2][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[2][10].value).toBe("]");
-      expect(tokens[2][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
-      expect(tokens[2][11].value).toBe("'");
-      expect(tokens[2][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[3][0].value).toBe("a");
-      expect(tokens[3][0].scopes).toEqual(["source.python"]);
-      expect(tokens[3][1].value).toBe(" ");
-      expect(tokens[3][1].scopes).toEqual(["source.python"]);
-      expect(tokens[3][2].value).toBe("=");
-      expect(tokens[3][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[3][3].value).toBe(" ");
-      expect(tokens[3][3].scopes).toEqual(["source.python"]);
-      expect(tokens[3][4].value).toBe("rF");
-      expect(tokens[3][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[3][5].value).toBe("'");
-      expect(tokens[3][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[3][6].value).toBe("[");
-      expect(tokens[3][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.begin.regexp"]);
-      expect(tokens[3][7].value).toBe("a");
-      expect(tokens[3][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[3][8].value).toBe("-");
-      expect(tokens[3][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[3][9].value).toBe("z");
-      expect(tokens[3][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.character.set.regexp"]);
-      expect(tokens[3][10].value).toBe("]");
-      expect(tokens[3][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","meta.character.set.regexp","constant.other.set.regexp punctuation.character.set.end.regexp"]);
-      expect(tokens[3][11].value).toBe("'");
-      expect(tokens[3][11].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-    });
-
-  it("test/regexp/fregexp2.py", 
-    function() {
-      tokens = grammar.tokenizeLines("rf'fo{{2}}'\nrf\"fo{{2}}\"\nrf'''fo{{2}}'''\nrf\"\"\"fo{{2}}\"\"\"")
-      expect(tokens[0][0].value).toBe("rf");
-      expect(tokens[0][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[0][1].value).toBe("'");
-      expect(tokens[0][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[0][2].value).toBe("fo");
-      expect(tokens[0][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[0][3].value).toBe("{{2}}");
-      expect(tokens[0][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
-      expect(tokens[0][4].value).toBe("'");
-      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[1][0].value).toBe("rf");
-      expect(tokens[1][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[1][1].value).toBe("\"");
-      expect(tokens[1][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[1][2].value).toBe("fo");
-      expect(tokens[1][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[1][3].value).toBe("{{2}}");
-      expect(tokens[1][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
-      expect(tokens[1][4].value).toBe("\"");
-      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[2][0].value).toBe("rf");
-      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[2][1].value).toBe("'''");
-      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[2][2].value).toBe("fo");
-      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
-      expect(tokens[2][3].value).toBe("{{2}}");
-      expect(tokens[2][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
-      expect(tokens[2][4].value).toBe("'''");
-      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[3][0].value).toBe("rf");
-      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[3][1].value).toBe("\"\"\"");
-      expect(tokens[3][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[3][2].value).toBe("fo");
-      expect(tokens[3][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
-      expect(tokens[3][3].value).toBe("{{2}}");
-      expect(tokens[3][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
-      expect(tokens[3][4].value).toBe("\"\"\"");
-      expect(tokens[3][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.end.python"]);
-    });
-
-  it("test/regexp/fregexp3.py", 
-    function() {
-      tokens = grammar.tokenizeLines("rf'fo{2}'\nrf\"fo{2}\"\nrf'''fo{2}'''\nrf\"\"\"fo{2}\"\"\"")
-      expect(tokens[0][0].value).toBe("rf");
-      expect(tokens[0][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[0][1].value).toBe("'");
-      expect(tokens[0][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[0][2].value).toBe("fo");
-      expect(tokens[0][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[0][3].value).toBe("{2}");
-      expect(tokens[0][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[0][4].value).toBe("'");
-      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[1][0].value).toBe("rf");
-      expect(tokens[1][0].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[1][1].value).toBe("\"");
-      expect(tokens[1][1].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[1][2].value).toBe("fo");
-      expect(tokens[1][2].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[1][3].value).toBe("{2}");
-      expect(tokens[1][3].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[1][4].value).toBe("\"");
-      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[2][0].value).toBe("rf");
-      expect(tokens[2][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[2][1].value).toBe("'''");
-      expect(tokens[2][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[2][2].value).toBe("fo");
-      expect(tokens[2][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
-      expect(tokens[2][3].value).toBe("{2}");
-      expect(tokens[2][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
-      expect(tokens[2][4].value).toBe("'''");
-      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[3][0].value).toBe("rf");
-      expect(tokens[3][0].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[3][1].value).toBe("\"\"\"");
-      expect(tokens[3][1].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[3][2].value).toBe("fo");
-      expect(tokens[3][2].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
-      expect(tokens[3][3].value).toBe("{2}");
-      expect(tokens[3][3].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python"]);
-      expect(tokens[3][4].value).toBe("\"\"\"");
-      expect(tokens[3][4].scopes).toEqual(["source.python","string.regexp.quoted.multi.python string.interpolated.python","punctuation.definition.string.end.python"]);
-    });
-
-  it("test/regexp/fregexp4.py", 
-    function() {
-      tokens = grammar.tokenizeLines("a = rf'fo{{2}}'\na = r'fo{{2}}'\na = r'fo{2}'")
-      expect(tokens[0][0].value).toBe("a");
-      expect(tokens[0][0].scopes).toEqual(["source.python"]);
-      expect(tokens[0][1].value).toBe(" ");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
-      expect(tokens[0][2].value).toBe("=");
-      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[0][3].value).toBe(" ");
-      expect(tokens[0][3].scopes).toEqual(["source.python"]);
-      expect(tokens[0][4].value).toBe("rf");
-      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[0][5].value).toBe("'");
-      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[0][6].value).toBe("fo");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[0][7].value).toBe("{{2}}");
-      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
-      expect(tokens[0][8].value).toBe("'");
-      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[1][0].value).toBe("a");
-      expect(tokens[1][0].scopes).toEqual(["source.python"]);
-      expect(tokens[1][1].value).toBe(" ");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
-      expect(tokens[1][2].value).toBe("=");
-      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[1][3].value).toBe(" ");
-      expect(tokens[1][3].scopes).toEqual(["source.python"]);
-      expect(tokens[1][4].value).toBe("r");
-      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
-      expect(tokens[1][5].value).toBe("'");
-      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[1][6].value).toBe("fo{");
-      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
-      expect(tokens[1][7].value).toBe("{2}");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.quantifier.regexp"]);
-      expect(tokens[1][8].value).toBe("}");
-      expect(tokens[1][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
-      expect(tokens[1][9].value).toBe("'");
-      expect(tokens[1][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
-      expect(tokens[2][0].value).toBe("a");
-      expect(tokens[2][0].scopes).toEqual(["source.python"]);
-      expect(tokens[2][1].value).toBe(" ");
-      expect(tokens[2][1].scopes).toEqual(["source.python"]);
-      expect(tokens[2][2].value).toBe("=");
-      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[2][3].value).toBe(" ");
-      expect(tokens[2][3].scopes).toEqual(["source.python"]);
-      expect(tokens[2][4].value).toBe("r");
-      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
-      expect(tokens[2][5].value).toBe("'");
-      expect(tokens[2][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[2][6].value).toBe("fo");
-      expect(tokens[2][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
-      expect(tokens[2][7].value).toBe("{2}");
-      expect(tokens[2][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python","keyword.operator.quantifier.regexp"]);
-      expect(tokens[2][8].value).toBe("'");
-      expect(tokens[2][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
-    });
-
-  it("test/regexp/fregexp5.py", 
-    function() {
-      tokens = grammar.tokenizeLines("a = rf'{{foo}}'\na = r'\\{foo\\}'")
-      expect(tokens[0][0].value).toBe("a");
-      expect(tokens[0][0].scopes).toEqual(["source.python"]);
-      expect(tokens[0][1].value).toBe(" ");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
-      expect(tokens[0][2].value).toBe("=");
-      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[0][3].value).toBe(" ");
-      expect(tokens[0][3].scopes).toEqual(["source.python"]);
-      expect(tokens[0][4].value).toBe("rf");
-      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[0][5].value).toBe("'");
-      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[0][6].value).toBe("{{");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
-      expect(tokens[0][7].value).toBe("foo");
-      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[0][8].value).toBe("}}");
-      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
-      expect(tokens[0][9].value).toBe("'");
-      expect(tokens[0][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[1][0].value).toBe("a");
-      expect(tokens[1][0].scopes).toEqual(["source.python"]);
-      expect(tokens[1][1].value).toBe(" ");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
-      expect(tokens[1][2].value).toBe("=");
-      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[1][3].value).toBe(" ");
-      expect(tokens[1][3].scopes).toEqual(["source.python"]);
-      expect(tokens[1][4].value).toBe("r");
-      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python","storage.type.string.python"]);
-      expect(tokens[1][5].value).toBe("'");
-      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[1][6].value).toBe("\\{");
-      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python","constant.character.escape.regexp"]);
-      expect(tokens[1][7].value).toBe("foo");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python"]);
-      expect(tokens[1][8].value).toBe("\\}");
-      expect(tokens[1][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python","constant.character.escape.regexp"]);
-      expect(tokens[1][9].value).toBe("'");
-      expect(tokens[1][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python","punctuation.definition.string.end.python"]);
-    });
-
-  it("test/regexp/fregexp6.py", 
-    function() {
-      tokens = grammar.tokenizeLines("a = rf'fo{{{2}}}'\na = rf'fo{{{bar}}}'\na = rf'fo{{2}}'")
-      expect(tokens[0][0].value).toBe("a");
-      expect(tokens[0][0].scopes).toEqual(["source.python"]);
-      expect(tokens[0][1].value).toBe(" ");
-      expect(tokens[0][1].scopes).toEqual(["source.python"]);
-      expect(tokens[0][2].value).toBe("=");
-      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[0][3].value).toBe(" ");
-      expect(tokens[0][3].scopes).toEqual(["source.python"]);
-      expect(tokens[0][4].value).toBe("rf");
-      expect(tokens[0][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[0][5].value).toBe("'");
-      expect(tokens[0][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[0][6].value).toBe("fo");
-      expect(tokens[0][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[0][7].value).toBe("{{");
-      expect(tokens[0][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
-      expect(tokens[0][8].value).toBe("{2}");
-      expect(tokens[0][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[0][9].value).toBe("}}");
-      expect(tokens[0][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
-      expect(tokens[0][10].value).toBe("'");
-      expect(tokens[0][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[1][0].value).toBe("a");
-      expect(tokens[1][0].scopes).toEqual(["source.python"]);
-      expect(tokens[1][1].value).toBe(" ");
-      expect(tokens[1][1].scopes).toEqual(["source.python"]);
-      expect(tokens[1][2].value).toBe("=");
-      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[1][3].value).toBe(" ");
-      expect(tokens[1][3].scopes).toEqual(["source.python"]);
-      expect(tokens[1][4].value).toBe("rf");
-      expect(tokens[1][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[1][5].value).toBe("'");
-      expect(tokens[1][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[1][6].value).toBe("fo");
-      expect(tokens[1][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[1][7].value).toBe("{{");
-      expect(tokens[1][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
-      expect(tokens[1][8].value).toBe("{bar}");
-      expect(tokens[1][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[1][9].value).toBe("}}");
-      expect(tokens[1][9].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","constant.character.escape.python"]);
-      expect(tokens[1][10].value).toBe("'");
-      expect(tokens[1][10].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-      expect(tokens[2][0].value).toBe("a");
-      expect(tokens[2][0].scopes).toEqual(["source.python"]);
-      expect(tokens[2][1].value).toBe(" ");
-      expect(tokens[2][1].scopes).toEqual(["source.python"]);
-      expect(tokens[2][2].value).toBe("=");
-      expect(tokens[2][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
-      expect(tokens[2][3].value).toBe(" ");
-      expect(tokens[2][3].scopes).toEqual(["source.python"]);
-      expect(tokens[2][4].value).toBe("rf");
-      expect(tokens[2][4].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","storage.type.string.python"]);
-      expect(tokens[2][5].value).toBe("'");
-      expect(tokens[2][5].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.begin.python"]);
-      expect(tokens[2][6].value).toBe("fo");
-      expect(tokens[2][6].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python"]);
-      expect(tokens[2][7].value).toBe("{{2}}");
-      expect(tokens[2][7].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","keyword.operator.quantifier.regexp"]);
-      expect(tokens[2][8].value).toBe("'");
-      expect(tokens[2][8].scopes).toEqual(["source.python","string.regexp.quoted.single.python string.interpolated.python","punctuation.definition.string.end.python"]);
-    });
-
   it("test/regexp/python1.py", 
     function() {
       tokens = grammar.tokenizeLines("a = r'[a-z]'\na = R'[a-z]'")
diff --git a/test/fstrings/empty2.py b/test/fstrings/empty2.py
index 77dc9087..9a007e14 100644
--- a/test/fstrings/empty2.py
+++ b/test/fstrings/empty2.py
@@ -7,20 +7,22 @@
 
 
 
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-"             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-{             : constant.character.format.placeholder.other.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-}             : constant.character.format.placeholder.other.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-              : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{             : constant.character.format.placeholder.other.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-              : invalid.illegal.brace.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-}             : constant.character.format.placeholder.other.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-"             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.multi.python
-"""           : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-{             : constant.character.format.placeholder.other.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-}             : constant.character.format.placeholder.other.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-{             : constant.character.format.placeholder.other.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-              : invalid.illegal.brace.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-}             : constant.character.format.placeholder.other.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-"""           : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+"             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+              : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+              : invalid.illegal.brace.python, meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+"             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.multi.python
+"""           : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.multi.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+              : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+              : invalid.illegal.brace.python, meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+              : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
+"""           : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
diff --git a/test/fstrings/fraw1.py b/test/fstrings/fraw1.py
new file mode 100644
index 00000000..31e2196e
--- /dev/null
+++ b/test/fstrings/fraw1.py
@@ -0,0 +1,40 @@
+a = fr'[a-z]'
+a = Fr'[a-z]'
+a = rf'[a-z]'
+a = rF'[a-z]'
+
+
+
+
+a             : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+fr            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+[a-z]         : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+a             : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+Fr            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+[a-z]         : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+a             : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+[a-z]         : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+a             : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+rF            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+[a-z]         : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
diff --git a/test/fstrings/fraw2.py b/test/fstrings/fraw2.py
new file mode 100644
index 00000000..df0a2fed
--- /dev/null
+++ b/test/fstrings/fraw2.py
@@ -0,0 +1,36 @@
+rf'fo{{2}}'
+rf"fo{{2}}"
+rf'''fo{{2}}'''
+rf"""fo{{2}}"""
+
+
+
+
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+fo            : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{{            : constant.character.escape.python, meta.fstring.python, source.python
+2             : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+}}            : constant.character.escape.python, meta.fstring.python, source.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+"             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+fo            : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{{            : constant.character.escape.python, meta.fstring.python, source.python
+2             : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+}}            : constant.character.escape.python, meta.fstring.python, source.python
+"             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.multi.python
+'''           : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.multi.python
+fo            : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
+{{            : constant.character.escape.python, meta.fstring.python, source.python
+2             : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
+}}            : constant.character.escape.python, meta.fstring.python, source.python
+'''           : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.multi.python
+"""           : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.multi.python
+fo            : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
+{{            : constant.character.escape.python, meta.fstring.python, source.python
+2             : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
+}}            : constant.character.escape.python, meta.fstring.python, source.python
+"""           : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
diff --git a/test/fstrings/fraw3.py b/test/fstrings/fraw3.py
new file mode 100644
index 00000000..da1a6aff
--- /dev/null
+++ b/test/fstrings/fraw3.py
@@ -0,0 +1,36 @@
+rf'fo{2}'
+rf"fo{2}"
+rf'''fo{2}'''
+rf"""fo{2}"""
+
+
+
+
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+fo            : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+2             : constant.numeric.dec.python, meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+"             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+fo            : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+2             : constant.numeric.dec.python, meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+"             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.multi.python
+'''           : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.multi.python
+fo            : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+2             : constant.numeric.dec.python, meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+'''           : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.multi.python
+"""           : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.multi.python
+fo            : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+2             : constant.numeric.dec.python, meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+"""           : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.multi.python
diff --git a/test/fstrings/fraw4.py b/test/fstrings/fraw4.py
new file mode 100644
index 00000000..2bf2d465
--- /dev/null
+++ b/test/fstrings/fraw4.py
@@ -0,0 +1,45 @@
+a = rf'fo{{{2}}}'
+a = rf'fo{{{bar}}}'
+a = rf'fo{{2}}'
+
+
+
+
+
+a             : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+fo            : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{{            : constant.character.escape.python, meta.fstring.python, source.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+2             : constant.numeric.dec.python, meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+}}            : constant.character.escape.python, meta.fstring.python, source.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+a             : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+fo            : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{{            : constant.character.escape.python, meta.fstring.python, source.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+bar           : meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+}}            : constant.character.escape.python, meta.fstring.python, source.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+a             : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+fo            : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{{            : constant.character.escape.python, meta.fstring.python, source.python
+2             : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+}}            : constant.character.escape.python, meta.fstring.python, source.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
diff --git a/test/fstrings/prefixes2.py b/test/fstrings/prefixes2.py
index 861d2b66..78ee4246 100644
--- a/test/fstrings/prefixes2.py
+++ b/test/fstrings/prefixes2.py
@@ -22,16 +22,20 @@
 obj           : meta.fstring.python, source.python
 }             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
 '             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-some          : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{obj}         : source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-rF            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-some          : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{obj}         : source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
+rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+some          : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+obj           : meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+rF            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+some          : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+obj           : meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
 Rf            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
 '             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
 some          : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
diff --git a/test/fstrings/prefixes3.py b/test/fstrings/prefixes3.py
index 200fa896..46d12ffb 100644
--- a/test/fstrings/prefixes3.py
+++ b/test/fstrings/prefixes3.py
@@ -6,16 +6,20 @@
 
 
 
-fr            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-some          : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{obj}         : source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-Fr            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-some          : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{obj}         : source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
+fr            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+some          : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+obj           : meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+Fr            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
+some          : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+obj           : meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.raw.single.python
 fR            : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.raw.single.python
 '             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.quoted.raw.single.python
 some          : meta.fstring.python, source.python, string.interpolated.python, string.quoted.raw.single.python
diff --git a/test/regexp/fregexp1.py b/test/regexp/fregexp1.py
deleted file mode 100644
index 9e77d66b..00000000
--- a/test/regexp/fregexp1.py
+++ /dev/null
@@ -1,56 +0,0 @@
-a = fr'[a-z]'
-a = Fr'[a-z]'
-a = rf'[a-z]'
-a = rF'[a-z]'
-
-
-
-
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-fr            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-[             : constant.other.set.regexp, meta.character.set.regexp, punctuation.character.set.begin.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-a             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
--             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-z             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-]             : constant.other.set.regexp, meta.character.set.regexp, punctuation.character.set.end.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-Fr            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-[             : constant.other.set.regexp, meta.character.set.regexp, punctuation.character.set.begin.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-a             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
--             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-z             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-]             : constant.other.set.regexp, meta.character.set.regexp, punctuation.character.set.end.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-[             : constant.other.set.regexp, meta.character.set.regexp, punctuation.character.set.begin.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-a             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
--             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-z             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-]             : constant.other.set.regexp, meta.character.set.regexp, punctuation.character.set.end.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-rF            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-[             : constant.other.set.regexp, meta.character.set.regexp, punctuation.character.set.begin.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-a             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
--             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-z             : constant.character.set.regexp, meta.character.set.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-]             : constant.other.set.regexp, meta.character.set.regexp, punctuation.character.set.end.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
diff --git a/test/regexp/fregexp2.py b/test/regexp/fregexp2.py
deleted file mode 100644
index 72eccc28..00000000
--- a/test/regexp/fregexp2.py
+++ /dev/null
@@ -1,28 +0,0 @@
-rf'fo{{2}}'
-rf"fo{{2}}"
-rf'''fo{{2}}'''
-rf"""fo{{2}}"""
-
-
-
-
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{{2}}         : keyword.operator.quantifier.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-"             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{{2}}         : keyword.operator.quantifier.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-"             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.multi.python
-'''           : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.multi.python
-{{2}}         : keyword.operator.quantifier.regexp, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-'''           : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.multi.python
-"""           : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.multi.python
-{{2}}         : keyword.operator.quantifier.regexp, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-"""           : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
diff --git a/test/regexp/fregexp3.py b/test/regexp/fregexp3.py
deleted file mode 100644
index ede8a6c3..00000000
--- a/test/regexp/fregexp3.py
+++ /dev/null
@@ -1,28 +0,0 @@
-rf'fo{2}'
-rf"fo{2}"
-rf'''fo{2}'''
-rf"""fo{2}"""
-
-
-
-
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{2}           : source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-"             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{2}           : source.python, string.interpolated.python, string.regexp.quoted.single.python
-"             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.multi.python
-'''           : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.multi.python
-{2}           : source.python, string.interpolated.python, string.regexp.quoted.multi.python
-'''           : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.multi.python
-"""           : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.multi.python
-{2}           : source.python, string.interpolated.python, string.regexp.quoted.multi.python
-"""           : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.multi.python
diff --git a/test/regexp/fregexp4.py b/test/regexp/fregexp4.py
deleted file mode 100644
index 5b707ad3..00000000
--- a/test/regexp/fregexp4.py
+++ /dev/null
@@ -1,36 +0,0 @@
-a = rf'fo{{2}}'
-a = r'fo{{2}}'
-a = r'fo{2}'
-
-
-
-
-
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{{2}}         : keyword.operator.quantifier.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-r             : source.python, storage.type.string.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.regexp.quoted.single.python
-fo{           : source.python, string.regexp.quoted.single.python
-{2}           : keyword.operator.quantifier.regexp, source.python, string.regexp.quoted.single.python
-}             : source.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.regexp.quoted.single.python
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-r             : source.python, storage.type.string.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.regexp.quoted.single.python
-fo            : source.python, string.regexp.quoted.single.python
-{2}           : keyword.operator.quantifier.regexp, source.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.regexp.quoted.single.python
diff --git a/test/regexp/fregexp5.py b/test/regexp/fregexp5.py
deleted file mode 100644
index 0d339e27..00000000
--- a/test/regexp/fregexp5.py
+++ /dev/null
@@ -1,26 +0,0 @@
-a = rf'{{foo}}'
-a = r'\{foo\}'
-
-
-
-
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-{{            : constant.character.escape.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-foo           : source.python, string.interpolated.python, string.regexp.quoted.single.python
-}}            : constant.character.escape.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-r             : source.python, storage.type.string.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.regexp.quoted.single.python
-\{            : constant.character.escape.regexp, source.python, string.regexp.quoted.single.python
-foo           : source.python, string.regexp.quoted.single.python
-\}            : constant.character.escape.regexp, source.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.regexp.quoted.single.python
diff --git a/test/regexp/fregexp6.py b/test/regexp/fregexp6.py
deleted file mode 100644
index a51311d0..00000000
--- a/test/regexp/fregexp6.py
+++ /dev/null
@@ -1,39 +0,0 @@
-a = rf'fo{{{2}}}'
-a = rf'fo{{{bar}}}'
-a = rf'fo{{2}}'
-
-
-
-
-
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{{            : constant.character.escape.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-{2}           : source.python, string.interpolated.python, string.regexp.quoted.single.python
-}}            : constant.character.escape.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{{            : constant.character.escape.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-{bar}         : source.python, string.interpolated.python, string.regexp.quoted.single.python
-}}            : constant.character.escape.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-a             : source.python
-              : source.python
-=             : keyword.operator.assignment.python, source.python
-              : source.python
-rf            : source.python, storage.type.string.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.regexp.quoted.single.python
-fo            : source.python, string.interpolated.python, string.regexp.quoted.single.python
-{{2}}         : keyword.operator.quantifier.regexp, source.python, string.interpolated.python, string.regexp.quoted.single.python
-'             : punctuation.definition.string.end.python, source.python, string.interpolated.python, string.regexp.quoted.single.python

From 7d0f2b22a5ad8fccbd7341bc7b7a715169283044 Mon Sep 17 00:00:00 2001
From: Victor Petrovykh <victor@edgedb.com>
Date: Tue, 18 Oct 2022 03:43:20 -0400
Subject: [PATCH 65/65] Update the syntax to Python 3.10

Update the built-ins, dunders and add `match` and `case` keywords.
---
 grammars/MagicPython.cson            |   81 +-
 grammars/MagicPython.tmLanguage      |   85 +-
 grammars/src/MagicPython.syntax.yaml |   76 +-
 test/atom-spec/python-spec.js        | 1210 +++++++++++++++++++++++++-
 test/builtins/builtins3.py           |   12 +
 test/builtins/builtins7.py           |    8 +
 test/classes/class9.py               |   16 +
 test/expressions/expr22.py           |   33 +
 test/expressions/special2.py         |    2 +-
 test/statements/match1.py            |   61 ++
 test/statements/match2.py            |  112 +++
 test/statements/match3.py            |  114 +++
 test/statements/match4.py            |   59 ++
 test/statements/match5.py            |  112 +++
 test/statements/match6.py            |   53 ++
 test/statements/match7.py            |   97 +++
 16 files changed, 2028 insertions(+), 103 deletions(-)
 create mode 100644 test/expressions/expr22.py
 create mode 100644 test/statements/match1.py
 create mode 100644 test/statements/match2.py
 create mode 100644 test/statements/match3.py
 create mode 100644 test/statements/match4.py
 create mode 100644 test/statements/match5.py
 create mode 100644 test/statements/match6.py
 create mode 100644 test/statements/match7.py

diff --git a/grammars/MagicPython.cson b/grammars/MagicPython.cson
index afb32a6d..d837d6a3 100644
--- a/grammars/MagicPython.cson
+++ b/grammars/MagicPython.cson
@@ -308,6 +308,18 @@ repository:
         name: "storage.type.class.python"
         match: "\\b(?<!\\.)(class)\\b"
       }
+      {
+        match: '''
+          (?x)
+            ^\\s*(
+              case | match
+            )(?=\\s*([-+\\w\\d(\\[{'":#]|$))\\b
+          
+        '''
+        captures:
+          "1":
+            name: "keyword.control.flow.python"
+      }
     ]
   "expression-bare":
     comment: "valid Python expressions w/o comments and line continuation"
@@ -1826,14 +1838,14 @@ repository:
         match: '''
           (?x)
             (?<!\\.) \\b(
-              __import__ | abs | all | any | ascii | bin | breakpoint | callable
-              | chr | compile | copyright | credits | delattr | dir | divmod
-              | enumerate | eval | exec | exit | filter | format | getattr
-              | globals | hasattr | hash | help | hex | id | input
-              | isinstance | issubclass | iter | len | license | locals | map
-              | max | memoryview | min | next | oct | open | ord | pow | print
-              | quit | range | reload | repr | reversed | round
-              | setattr | sorted | sum | vars | zip
+              __import__ | abs | aiter | all | any | anext | ascii | bin
+              | breakpoint | callable | chr | compile | copyright | credits
+              | delattr | dir | divmod | enumerate | eval | exec | exit
+              | filter | format | getattr | globals | hasattr | hash | help
+              | hex | id | input | isinstance | issubclass | iter | len
+              | license | locals | map | max | memoryview | min | next
+              | oct | open | ord | pow | print | quit | range | reload | repr
+              | reversed | round | setattr | sorted | sum | vars | zip
             )\\b
           
         '''
@@ -1876,24 +1888,29 @@ repository:
       (?x)
         \\b(
           __(?:
-            abs | add | aenter | aexit | aiter | and | anext | await
-            | bool | call | ceil | cmp | coerce | complex | contains
-            | copy | deepcopy | del | delattr | delete | delitem
-            | delslice | dir | div | divmod | enter | eq | exit | float
-            | floor | floordiv | format | ge | get | getattr
-            | getattribute | getinitargs | getitem | getnewargs
-            | getslice | getstate | gt | hash | hex | iadd | iand | idiv
-            | ifloordiv | ilshift | imod | imul | index | init
-            | instancecheck | int | invert | ior | ipow | irshift | isub
-            | iter | itruediv | ixor | le | len | long | lshift | lt
-            | missing | mod | mul | ne | neg | new | next | nonzero | oct | or
-            | pos | pow | radd | rand | rdiv | rdivmod | reduce
-            | reduce_ex | repr | reversed | rfloordiv | rlshift | rmod
-            | rmul | ror | round | rpow | rrshift | rshift | rsub
-            | rtruediv | rxor | set | setattr | setitem | setslice
-            | setstate | sizeof | str | sub | subclasscheck | truediv
-            | trunc | unicode | xor | matmul | rmatmul | imatmul
-            | init_subclass | set_name | fspath | bytes | prepare
+            abs | add | aenter | aexit | aiter | and | anext
+            | await | bool | call | ceil | class_getitem
+            | cmp | coerce | complex | contains | copy
+            | deepcopy | del | delattr | delete | delitem
+            | delslice | dir | div | divmod | enter | eq
+            | exit | float | floor | floordiv | format | ge
+            | get | getattr | getattribute | getinitargs
+            | getitem | getnewargs | getslice | getstate | gt
+            | hash | hex | iadd | iand | idiv | ifloordiv |
+            | ilshift | imod | imul | index | init
+            | instancecheck | int | invert | ior | ipow
+            | irshift | isub | iter | itruediv | ixor | le
+            | len | long | lshift | lt | missing | mod | mul
+            | ne | neg | new | next | nonzero | oct | or | pos
+            | pow | radd | rand | rdiv | rdivmod | reduce
+            | reduce_ex | repr | reversed | rfloordiv |
+            | rlshift | rmod | rmul | ror | round | rpow
+            | rrshift | rshift | rsub | rtruediv | rxor | set
+            | setattr | setitem | set_name | setslice
+            | setstate | sizeof | str | sub | subclasscheck
+            | truediv | trunc | unicode | xor | matmul
+            | rmatmul | imatmul | init_subclass | set_name
+            | fspath | bytes | prepare | length_hint
           )__
         )\\b
       
@@ -1907,12 +1924,12 @@ repository:
       (?x)
         \\b(
           __(?:
-            all | bases | builtins | class | class_getitem | code | debug
-            | defaults | dict | doc | file | func | kwdefaults | members
-            | metaclass | methods | module | mro | mro_entries | name
-            | qualname | post_init | self | signature | slots | subclasses
-            | version | weakref | wrapped | annotations | classcell
-            | spec | path | package | future | traceback
+            all | annotations | bases | builtins | class
+            | closure | code | debug | defaults | dict | doc | file | func
+            | globals | kwdefaults | match_args | members | metaclass | methods
+            | module | mro | mro_entries | name | qualname | post_init | self
+            | signature | slots | subclasses | version | weakref | wrapped
+            | classcell | spec | path | package | future | traceback
           )__
         )\\b
       
diff --git a/grammars/MagicPython.tmLanguage b/grammars/MagicPython.tmLanguage
index a3f1bd2b..a1c3f8e7 100644
--- a/grammars/MagicPython.tmLanguage
+++ b/grammars/MagicPython.tmLanguage
@@ -471,6 +471,22 @@ it's probably control flow like:
             <key>match</key>
             <string>\b(?&lt;!\.)(class)\b</string>
           </dict>
+          <dict>
+            <key>match</key>
+            <string>(?x)
+  ^\s*(
+    case | match
+  )(?=\s*([-+\w\d(\[{'":#]|$))\b
+</string>
+            <key>captures</key>
+            <dict>
+              <key>1</key>
+              <dict>
+                <key>name</key>
+                <string>keyword.control.flow.python</string>
+              </dict>
+            </dict>
+          </dict>
         </array>
       </dict>
       <key>expression-bare</key>
@@ -2852,14 +2868,14 @@ correctly identify the "in" as a control flow keyword.
             <key>match</key>
             <string>(?x)
   (?&lt;!\.) \b(
-    __import__ | abs | all | any | ascii | bin | breakpoint | callable
-    | chr | compile | copyright | credits | delattr | dir | divmod
-    | enumerate | eval | exec | exit | filter | format | getattr
-    | globals | hasattr | hash | help | hex | id | input
-    | isinstance | issubclass | iter | len | license | locals | map
-    | max | memoryview | min | next | oct | open | ord | pow | print
-    | quit | range | reload | repr | reversed | round
-    | setattr | sorted | sum | vars | zip
+    __import__ | abs | aiter | all | any | anext | ascii | bin
+    | breakpoint | callable | chr | compile | copyright | credits
+    | delattr | dir | divmod | enumerate | eval | exec | exit
+    | filter | format | getattr | globals | hasattr | hash | help
+    | hex | id | input | isinstance | issubclass | iter | len
+    | license | locals | map | max | memoryview | min | next
+    | oct | open | ord | pow | print | quit | range | reload | repr
+    | reversed | round | setattr | sorted | sum | vars | zip
   )\b
 </string>
           </dict>
@@ -2904,24 +2920,29 @@ indirectly through syntactic constructs
         <string>(?x)
   \b(
     __(?:
-      abs | add | aenter | aexit | aiter | and | anext | await
-      | bool | call | ceil | cmp | coerce | complex | contains
-      | copy | deepcopy | del | delattr | delete | delitem
-      | delslice | dir | div | divmod | enter | eq | exit | float
-      | floor | floordiv | format | ge | get | getattr
-      | getattribute | getinitargs | getitem | getnewargs
-      | getslice | getstate | gt | hash | hex | iadd | iand | idiv
-      | ifloordiv | ilshift | imod | imul | index | init
-      | instancecheck | int | invert | ior | ipow | irshift | isub
-      | iter | itruediv | ixor | le | len | long | lshift | lt
-      | missing | mod | mul | ne | neg | new | next | nonzero | oct | or
-      | pos | pow | radd | rand | rdiv | rdivmod | reduce
-      | reduce_ex | repr | reversed | rfloordiv | rlshift | rmod
-      | rmul | ror | round | rpow | rrshift | rshift | rsub
-      | rtruediv | rxor | set | setattr | setitem | setslice
-      | setstate | sizeof | str | sub | subclasscheck | truediv
-      | trunc | unicode | xor | matmul | rmatmul | imatmul
-      | init_subclass | set_name | fspath | bytes | prepare
+      abs | add | aenter | aexit | aiter | and | anext
+      | await | bool | call | ceil | class_getitem
+      | cmp | coerce | complex | contains | copy
+      | deepcopy | del | delattr | delete | delitem
+      | delslice | dir | div | divmod | enter | eq
+      | exit | float | floor | floordiv | format | ge
+      | get | getattr | getattribute | getinitargs
+      | getitem | getnewargs | getslice | getstate | gt
+      | hash | hex | iadd | iand | idiv | ifloordiv |
+      | ilshift | imod | imul | index | init
+      | instancecheck | int | invert | ior | ipow
+      | irshift | isub | iter | itruediv | ixor | le
+      | len | long | lshift | lt | missing | mod | mul
+      | ne | neg | new | next | nonzero | oct | or | pos
+      | pow | radd | rand | rdiv | rdivmod | reduce
+      | reduce_ex | repr | reversed | rfloordiv |
+      | rlshift | rmod | rmul | ror | round | rpow
+      | rrshift | rshift | rsub | rtruediv | rxor | set
+      | setattr | setitem | set_name | setslice
+      | setstate | sizeof | str | sub | subclasscheck
+      | truediv | trunc | unicode | xor | matmul
+      | rmatmul | imatmul | init_subclass | set_name
+      | fspath | bytes | prepare | length_hint
     )__
   )\b
 </string>
@@ -2942,12 +2963,12 @@ indirectly through syntactic constructs
         <string>(?x)
   \b(
     __(?:
-      all | bases | builtins | class | class_getitem | code | debug
-      | defaults | dict | doc | file | func | kwdefaults | members
-      | metaclass | methods | module | mro | mro_entries | name
-      | qualname | post_init | self | signature | slots | subclasses
-      | version | weakref | wrapped | annotations | classcell
-      | spec | path | package | future | traceback
+      all | annotations | bases | builtins | class
+      | closure | code | debug | defaults | dict | doc | file | func
+      | globals | kwdefaults | match_args | members | metaclass | methods
+      | module | mro | mro_entries | name | qualname | post_init | self
+      | signature | slots | subclasses | version | weakref | wrapped
+      | classcell | spec | path | package | future | traceback
     )__
   )\b
 </string>
diff --git a/grammars/src/MagicPython.syntax.yaml b/grammars/src/MagicPython.syntax.yaml
index bd740829..ebfccdaf 100644
--- a/grammars/src/MagicPython.syntax.yaml
+++ b/grammars/src/MagicPython.syntax.yaml
@@ -313,6 +313,13 @@ repository:
             )\b
       - name: storage.type.class.python
         match: \b(?<!\.)(class)\b
+      - match: |
+          (?x)
+            ^\s*(
+              case | match
+            )(?=\s*([-+\w\d(\[{'":#]|$))\b
+        captures:
+          '1': {name: keyword.control.flow.python}
 
   expression-bare:
     comment: valid Python expressions w/o comments and line continuation
@@ -1284,14 +1291,14 @@ repository:
         match: |
           (?x)
             (?<!\.) \b(
-              __import__ | abs | all | any | ascii | bin | breakpoint | callable
-              | chr | compile | copyright | credits | delattr | dir | divmod
-              | enumerate | eval | exec | exit | filter | format | getattr
-              | globals | hasattr | hash | help | hex | id | input
-              | isinstance | issubclass | iter | len | license | locals | map
-              | max | memoryview | min | next | oct | open | ord | pow | print
-              | quit | range | reload | repr | reversed | round
-              | setattr | sorted | sum | vars | zip
+              __import__ | abs | aiter | all | any | anext | ascii | bin
+              | breakpoint | callable | chr | compile | copyright | credits
+              | delattr | dir | divmod | enumerate | eval | exec | exit
+              | filter | format | getattr | globals | hasattr | hash | help
+              | hex | id | input | isinstance | issubclass | iter | len
+              | license | locals | map | max | memoryview | min | next
+              | oct | open | ord | pow | print | quit | range | reload | repr
+              | reversed | round | setattr | sorted | sum | vars | zip
             )\b
 
       - name: variable.legacy.builtin.python
@@ -1325,24 +1332,29 @@ repository:
       (?x)
         \b(
           __(?:
-            abs | add | aenter | aexit | aiter | and | anext | await
-            | bool | call | ceil | cmp | coerce | complex | contains
-            | copy | deepcopy | del | delattr | delete | delitem
-            | delslice | dir | div | divmod | enter | eq | exit | float
-            | floor | floordiv | format | ge | get | getattr
-            | getattribute | getinitargs | getitem | getnewargs
-            | getslice | getstate | gt | hash | hex | iadd | iand | idiv
-            | ifloordiv | ilshift | imod | imul | index | init
-            | instancecheck | int | invert | ior | ipow | irshift | isub
-            | iter | itruediv | ixor | le | len | long | lshift | lt
-            | missing | mod | mul | ne | neg | new | next | nonzero | oct | or
-            | pos | pow | radd | rand | rdiv | rdivmod | reduce
-            | reduce_ex | repr | reversed | rfloordiv | rlshift | rmod
-            | rmul | ror | round | rpow | rrshift | rshift | rsub
-            | rtruediv | rxor | set | setattr | setitem | setslice
-            | setstate | sizeof | str | sub | subclasscheck | truediv
-            | trunc | unicode | xor | matmul | rmatmul | imatmul
-            | init_subclass | set_name | fspath | bytes | prepare
+            abs | add | aenter | aexit | aiter | and | anext
+            | await | bool | call | ceil | class_getitem
+            | cmp | coerce | complex | contains | copy
+            | deepcopy | del | delattr | delete | delitem
+            | delslice | dir | div | divmod | enter | eq
+            | exit | float | floor | floordiv | format | ge
+            | get | getattr | getattribute | getinitargs
+            | getitem | getnewargs | getslice | getstate | gt
+            | hash | hex | iadd | iand | idiv | ifloordiv |
+            | ilshift | imod | imul | index | init
+            | instancecheck | int | invert | ior | ipow
+            | irshift | isub | iter | itruediv | ixor | le
+            | len | long | lshift | lt | missing | mod | mul
+            | ne | neg | new | next | nonzero | oct | or | pos
+            | pow | radd | rand | rdiv | rdivmod | reduce
+            | reduce_ex | repr | reversed | rfloordiv |
+            | rlshift | rmod | rmul | ror | round | rpow
+            | rrshift | rshift | rsub | rtruediv | rxor | set
+            | setattr | setitem | set_name | setslice
+            | setstate | sizeof | str | sub | subclasscheck
+            | truediv | trunc | unicode | xor | matmul
+            | rmatmul | imatmul | init_subclass | set_name
+            | fspath | bytes | prepare | length_hint
           )__
         )\b
     captures:
@@ -1354,12 +1366,12 @@ repository:
       (?x)
         \b(
           __(?:
-            all | bases | builtins | class | class_getitem | code | debug
-            | defaults | dict | doc | file | func | kwdefaults | members
-            | metaclass | methods | module | mro | mro_entries | name
-            | qualname | post_init | self | signature | slots | subclasses
-            | version | weakref | wrapped | annotations | classcell
-            | spec | path | package | future | traceback
+            all | annotations | bases | builtins | class
+            | closure | code | debug | defaults | dict | doc | file | func
+            | globals | kwdefaults | match_args | members | metaclass | methods
+            | module | mro | mro_entries | name | qualname | post_init | self
+            | signature | slots | subclasses | version | weakref | wrapped
+            | classcell | spec | path | package | future | traceback
           )__
         )\b
     captures:
diff --git a/test/atom-spec/python-spec.js b/test/atom-spec/python-spec.js
index cf00b257..79edf0a0 100644
--- a/test/atom-spec/python-spec.js
+++ b/test/atom-spec/python-spec.js
@@ -134,7 +134,7 @@ describe("Grammar Tests", function() {
 
   it("test/builtins/builtins3.py", 
     function() {
-      tokens = grammar.tokenizeLines("__all__ = ['bar', 'baz']\nsome.__bases__\nsome.__class__\nassert __debug__\n__builtins__\n__builtins__.len\nprint(__builtins__)\nsome.__dict__\nsome.__doc__\nsome.__file__\nsome.__members__\nsome.__metaclass__\nsome.__methods__\nsome.__module__\nsome.__mro__\nsome.__name__\nsome.__slots__\nsome.__subclasses__\nsome.__version__\nsome.__weakref__\nsome.__qualname__\nsome.__code__\nsome.__wrapped__\nsome.__signature__\nsome.__defaults__\nsome.__func__\nsome.__self__\nsome.__kwdefaults__\nsome.__matmul__\nsome.__imatmul__\nsome.__rmatmul__\nsome.__annotations__\nsome.__init_subclass__\nsome.__set_name__\nsome.__fspath__\nsome.__classcell__\nsome.__bytes__\nsome.__spec__\nsome.__path__\nsome.__prepare__\nsome.__package__\nsome.__traceback__\nsome.__notspecial__")
+      tokens = grammar.tokenizeLines("__all__ = ['bar', 'baz']\nsome.__bases__\nsome.__class__\nassert __debug__\n__builtins__\n__builtins__.len\nprint(__builtins__)\nsome.__dict__\nsome.__doc__\nsome.__file__\nsome.__members__\nsome.__metaclass__\nsome.__methods__\nsome.__module__\nsome.__mro__\nsome.__name__\nsome.__slots__\nsome.__subclasses__\nsome.__version__\nsome.__weakref__\nsome.__qualname__\nsome.__code__\nsome.__wrapped__\nsome.__signature__\nsome.__defaults__\nsome.__func__\nsome.__self__\nsome.__kwdefaults__\nsome.__matmul__\nsome.__imatmul__\nsome.__rmatmul__\nsome.__annotations__\nsome.__init_subclass__\nsome.__set_name__\nsome.__fspath__\nsome.__classcell__\nsome.__bytes__\nsome.__spec__\nsome.__path__\nsome.__prepare__\nsome.__package__\nsome.__traceback__\nsome.__closure__\nsome.__globals__\nsome.__match_args__\nsome.__notspecial__")
       expect(tokens[0][0].value).toBe("__all__");
       expect(tokens[0][0].scopes).toEqual(["source.python","support.variable.magic.python"]);
       expect(tokens[0][1].value).toBe(" ");
@@ -411,8 +411,26 @@ describe("Grammar Tests", function() {
       expect(tokens[42][0].scopes).toEqual(["source.python"]);
       expect(tokens[42][1].value).toBe(".");
       expect(tokens[42][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
-      expect(tokens[42][2].value).toBe("__notspecial__");
-      expect(tokens[42][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
+      expect(tokens[42][2].value).toBe("__closure__");
+      expect(tokens[42][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
+      expect(tokens[43][0].value).toBe("some");
+      expect(tokens[43][0].scopes).toEqual(["source.python"]);
+      expect(tokens[43][1].value).toBe(".");
+      expect(tokens[43][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
+      expect(tokens[43][2].value).toBe("__globals__");
+      expect(tokens[43][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
+      expect(tokens[44][0].value).toBe("some");
+      expect(tokens[44][0].scopes).toEqual(["source.python"]);
+      expect(tokens[44][1].value).toBe(".");
+      expect(tokens[44][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
+      expect(tokens[44][2].value).toBe("__match_args__");
+      expect(tokens[44][2].scopes).toEqual(["source.python","meta.member.access.python","support.variable.magic.python"]);
+      expect(tokens[45][0].value).toBe("some");
+      expect(tokens[45][0].scopes).toEqual(["source.python"]);
+      expect(tokens[45][1].value).toBe(".");
+      expect(tokens[45][1].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
+      expect(tokens[45][2].value).toBe("__notspecial__");
+      expect(tokens[45][2].scopes).toEqual(["source.python","meta.member.access.python","meta.attribute.python"]);
     });
 
   it("test/builtins/builtins4.py", 
@@ -516,13 +534,25 @@ describe("Grammar Tests", function() {
 
   it("test/builtins/builtins7.py", 
     function() {
-      tokens = grammar.tokenizeLines("breakpoint()")
+      tokens = grammar.tokenizeLines("breakpoint()\naiter()\nanext()")
       expect(tokens[0][0].value).toBe("breakpoint");
       expect(tokens[0][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
       expect(tokens[0][1].value).toBe("(");
       expect(tokens[0][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
       expect(tokens[0][2].value).toBe(")");
       expect(tokens[0][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][0].value).toBe("aiter");
+      expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[1][1].value).toBe("(");
+      expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][2].value).toBe(")");
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[2][0].value).toBe("anext");
+      expect(tokens[2][0].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[2][1].value).toBe("(");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][2].value).toBe(")");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
     });
 
   it("test/calls/call1.py", 
@@ -2056,7 +2086,7 @@ describe("Grammar Tests", function() {
 
   it("test/classes/class9.py", 
     function() {
-      tokens = grammar.tokenizeLines("class Foo:\n    __slots__ = ()")
+      tokens = grammar.tokenizeLines("class Foo:\n    __slots__ = ()\n    __match_args__ = ('key', 'name')")
       expect(tokens[0][0].value).toBe("class");
       expect(tokens[0][0].scopes).toEqual(["source.python","meta.class.python","storage.type.class.python"]);
       expect(tokens[0][1].value).toBe(" ");
@@ -2079,6 +2109,36 @@ describe("Grammar Tests", function() {
       expect(tokens[1][5].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
       expect(tokens[1][6].value).toBe(")");
       expect(tokens[1][6].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("__match_args__");
+      expect(tokens[2][1].scopes).toEqual(["source.python","support.variable.magic.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe("=");
+      expect(tokens[2][3].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[2][4].value).toBe(" ");
+      expect(tokens[2][4].scopes).toEqual(["source.python"]);
+      expect(tokens[2][5].value).toBe("(");
+      expect(tokens[2][5].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[2][6].value).toBe("'");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][7].value).toBe("key");
+      expect(tokens[2][7].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][8].value).toBe("'");
+      expect(tokens[2][8].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][9].value).toBe(",");
+      expect(tokens[2][9].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[2][10].value).toBe(" ");
+      expect(tokens[2][10].scopes).toEqual(["source.python"]);
+      expect(tokens[2][11].value).toBe("'");
+      expect(tokens[2][11].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][12].value).toBe("name");
+      expect(tokens[2][12].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][13].value).toBe("'");
+      expect(tokens[2][13].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][14].value).toBe(")");
+      expect(tokens[2][14].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
     });
 
   it("test/classes/super1.py", 
@@ -5871,6 +5931,63 @@ describe("Grammar Tests", function() {
       expect(tokens[2][14].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
     });
 
+  it("test/expressions/expr22.py", 
+    function() {
+      tokens = grammar.tokenizeLines("match = 13\ncase = 12\nif case == 4:\n  return match * 5")
+      expect(tokens[0][0].value).toBe("match");
+      expect(tokens[0][0].scopes).toEqual(["source.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("=");
+      expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[0][3].value).toBe(" ");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe("13");
+      expect(tokens[0][4].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[1][0].value).toBe("case");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe(" ");
+      expect(tokens[1][1].scopes).toEqual(["source.python"]);
+      expect(tokens[1][2].value).toBe("=");
+      expect(tokens[1][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][3].value).toBe(" ");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe("12");
+      expect(tokens[1][4].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[2][0].value).toBe("if");
+      expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("case");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe(" ");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe("==");
+      expect(tokens[2][4].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("4");
+      expect(tokens[2][6].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[2][7].value).toBe(":");
+      expect(tokens[2][7].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[3][0].value).toBe("  ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("return");
+      expect(tokens[3][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("match");
+      expect(tokens[3][3].scopes).toEqual(["source.python"]);
+      expect(tokens[3][4].value).toBe(" ");
+      expect(tokens[3][4].scopes).toEqual(["source.python"]);
+      expect(tokens[3][5].value).toBe("*");
+      expect(tokens[3][5].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[3][6].value).toBe(" ");
+      expect(tokens[3][6].scopes).toEqual(["source.python"]);
+      expect(tokens[3][7].value).toBe("5");
+      expect(tokens[3][7].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+    });
+
   it("test/expressions/expr3.py", 
     function() {
       tokens = grammar.tokenizeLines("(a, *rest, b) = range(5)")
@@ -6340,7 +6457,7 @@ describe("Grammar Tests", function() {
       expect(tokens[1][1].value).toBe(" ");
       expect(tokens[1][1].scopes).toEqual(["source.python","meta.function.python"]);
       expect(tokens[1][2].value).toBe("__class_getitem__");
-      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","support.variable.magic.python"]);
+      expect(tokens[1][2].scopes).toEqual(["source.python","meta.function.python","support.function.magic.python"]);
       expect(tokens[1][3].value).toBe("(");
       expect(tokens[1][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
       expect(tokens[1][4].value).toBe(")");
@@ -13174,6 +13291,1087 @@ describe("Grammar Tests", function() {
       expect(tokens[8][11].scopes).toEqual(["source.python","constant.language.python"]);
     });
 
+  it("test/statements/match1.py", 
+    function() {
+      tokens = grammar.tokenizeLines("def foo(status):\n    match status:\n        case 404:\n            return \"Not found\"\n        case 401 | 403:\n            return \"Not allowed\"\n        case _:\n            return \"Something's wrong with the internet\"")
+      expect(tokens[0][0].value).toBe("def");
+      expect(tokens[0][0].scopes).toEqual(["source.python","meta.function.python","storage.type.function.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python","meta.function.python"]);
+      expect(tokens[0][2].value).toBe("foo");
+      expect(tokens[0][2].scopes).toEqual(["source.python","meta.function.python","entity.name.function.python"]);
+      expect(tokens[0][3].value).toBe("(");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.begin.python"]);
+      expect(tokens[0][4].value).toBe("status");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","variable.parameter.function.language.python"]);
+      expect(tokens[0][5].value).toBe(")");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.function.python","meta.function.parameters.python","punctuation.definition.parameters.end.python"]);
+      expect(tokens[0][6].value).toBe(":");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.function.python","punctuation.section.function.begin.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("match");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("status");
+      expect(tokens[1][3].scopes).toEqual(["source.python"]);
+      expect(tokens[1][4].value).toBe(":");
+      expect(tokens[1][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[2][0].value).toBe("        ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("case");
+      expect(tokens[2][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe("404");
+      expect(tokens[2][3].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[2][4].value).toBe(":");
+      expect(tokens[2][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[3][0].value).toBe("            ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("return");
+      expect(tokens[3][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("\"");
+      expect(tokens[3][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[3][4].value).toBe("Not found");
+      expect(tokens[3][4].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[3][5].value).toBe("\"");
+      expect(tokens[3][5].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][0].value).toBe("        ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("case");
+      expect(tokens[4][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][2].value).toBe(" ");
+      expect(tokens[4][2].scopes).toEqual(["source.python"]);
+      expect(tokens[4][3].value).toBe("401");
+      expect(tokens[4][3].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[4][4].value).toBe(" ");
+      expect(tokens[4][4].scopes).toEqual(["source.python"]);
+      expect(tokens[4][5].value).toBe("|");
+      expect(tokens[4][5].scopes).toEqual(["source.python","keyword.operator.bitwise.python"]);
+      expect(tokens[4][6].value).toBe(" ");
+      expect(tokens[4][6].scopes).toEqual(["source.python"]);
+      expect(tokens[4][7].value).toBe("403");
+      expect(tokens[4][7].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
+      expect(tokens[4][8].value).toBe(":");
+      expect(tokens[4][8].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[5][0].value).toBe("            ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("return");
+      expect(tokens[5][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[5][2].value).toBe(" ");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][3].value).toBe("\"");
+      expect(tokens[5][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[5][4].value).toBe("Not allowed");
+      expect(tokens[5][4].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[5][5].value).toBe("\"");
+      expect(tokens[5][5].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[6][0].value).toBe("        ");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe("case");
+      expect(tokens[6][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[6][2].value).toBe(" ");
+      expect(tokens[6][2].scopes).toEqual(["source.python"]);
+      expect(tokens[6][3].value).toBe("_");
+      expect(tokens[6][3].scopes).toEqual(["source.python"]);
+      expect(tokens[6][4].value).toBe(":");
+      expect(tokens[6][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[7][0].value).toBe("            ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("return");
+      expect(tokens[7][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[7][2].value).toBe(" ");
+      expect(tokens[7][2].scopes).toEqual(["source.python"]);
+      expect(tokens[7][3].value).toBe("\"");
+      expect(tokens[7][3].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[7][4].value).toBe("Something's wrong with the internet");
+      expect(tokens[7][4].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[7][5].value).toBe("\"");
+      expect(tokens[7][5].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+    });
+
+  it("test/statements/match2.py", 
+    function() {
+      tokens = grammar.tokenizeLines("match point:\n    case Point(x=0, y=0):\n        print(\"Origin is the point's location.\")\n    case Point(x=0, y=y):\n        print(f\"The point is on the y-axis.\")\n    case Point(x=x, y=0):\n        print(f\"The point is on the x-axis.\")\n    case Point():\n        print(\"The point is located somewhere else on the plane.\")\n    case _:\n        print(\"Not a point\")")
+      expect(tokens[0][0].value).toBe("match");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("point");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("case");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("Point");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][4].value).toBe("(");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][5].value).toBe("x");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[1][6].value).toBe("=");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][7].value).toBe("0");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[1][8].value).toBe(",");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[1][9].value).toBe(" ");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][10].value).toBe("y");
+      expect(tokens[1][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[1][11].value).toBe("=");
+      expect(tokens[1][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[1][12].value).toBe("0");
+      expect(tokens[1][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[1][13].value).toBe(")");
+      expect(tokens[1][13].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][14].value).toBe(":");
+      expect(tokens[1][14].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[2][0].value).toBe("        ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("print");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[2][2].value).toBe("(");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][3].value).toBe("\"");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][4].value).toBe("Origin is the point's location.");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[2][5].value).toBe("\"");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][6].value).toBe(")");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("case");
+      expect(tokens[3][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("Point");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[3][4].value).toBe("(");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][5].value).toBe("x");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][6].value).toBe("=");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][7].value).toBe("0");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[3][8].value).toBe(",");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[3][9].value).toBe(" ");
+      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][10].value).toBe("y");
+      expect(tokens[3][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[3][11].value).toBe("=");
+      expect(tokens[3][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[3][12].value).toBe("y");
+      expect(tokens[3][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][13].value).toBe(")");
+      expect(tokens[3][13].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][14].value).toBe(":");
+      expect(tokens[3][14].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[4][0].value).toBe("        ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("print");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[4][2].value).toBe("(");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[4][3].value).toBe("f");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[4][4].value).toBe("\"");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[4][5].value).toBe("The point is on the y-axis.");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[4][6].value).toBe("\"");
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[4][7].value).toBe(")");
+      expect(tokens[4][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("case");
+      expect(tokens[5][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[5][2].value).toBe(" ");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][3].value).toBe("Point");
+      expect(tokens[5][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[5][4].value).toBe("(");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[5][5].value).toBe("x");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[5][6].value).toBe("=");
+      expect(tokens[5][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[5][7].value).toBe("x");
+      expect(tokens[5][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[5][8].value).toBe(",");
+      expect(tokens[5][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[5][9].value).toBe(" ");
+      expect(tokens[5][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[5][10].value).toBe("y");
+      expect(tokens[5][10].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
+      expect(tokens[5][11].value).toBe("=");
+      expect(tokens[5][11].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
+      expect(tokens[5][12].value).toBe("0");
+      expect(tokens[5][12].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[5][13].value).toBe(")");
+      expect(tokens[5][13].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[5][14].value).toBe(":");
+      expect(tokens[5][14].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[6][0].value).toBe("        ");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe("print");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[6][2].value).toBe("(");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[6][3].value).toBe("f");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[6][4].value).toBe("\"");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[6][5].value).toBe("The point is on the x-axis.");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[6][6].value).toBe("\"");
+      expect(tokens[6][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[6][7].value).toBe(")");
+      expect(tokens[6][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("case");
+      expect(tokens[7][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[7][2].value).toBe(" ");
+      expect(tokens[7][2].scopes).toEqual(["source.python"]);
+      expect(tokens[7][3].value).toBe("Point");
+      expect(tokens[7][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[7][4].value).toBe("(");
+      expect(tokens[7][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[7][5].value).toBe(")");
+      expect(tokens[7][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[7][6].value).toBe(":");
+      expect(tokens[7][6].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[8][0].value).toBe("        ");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe("print");
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[8][2].value).toBe("(");
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[8][3].value).toBe("\"");
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[8][4].value).toBe("The point is located somewhere else on the plane.");
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[8][5].value).toBe("\"");
+      expect(tokens[8][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[8][6].value).toBe(")");
+      expect(tokens[8][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[9][0].value).toBe("    ");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].value).toBe("case");
+      expect(tokens[9][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[9][2].value).toBe(" ");
+      expect(tokens[9][2].scopes).toEqual(["source.python"]);
+      expect(tokens[9][3].value).toBe("_");
+      expect(tokens[9][3].scopes).toEqual(["source.python"]);
+      expect(tokens[9][4].value).toBe(":");
+      expect(tokens[9][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[10][0].value).toBe("        ");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe("print");
+      expect(tokens[10][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[10][2].value).toBe("(");
+      expect(tokens[10][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[10][3].value).toBe("\"");
+      expect(tokens[10][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][4].value).toBe("Not a point");
+      expect(tokens[10][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[10][5].value).toBe("\"");
+      expect(tokens[10][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[10][6].value).toBe(")");
+      expect(tokens[10][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/statements/match3.py", 
+    function() {
+      tokens = grammar.tokenizeLines("match points:\n    case []:\n        print(\"No points in the list.\")\n    case [Point(0, 0)]:\n        print(\"The origin is the only point in the list.\")\n    case [Point(x, y)]:\n        print(f\"A single point is in the list.\")\n    case [Point(0, y1), Point(0, y2)]:\n        print(f\"Two points on the Y axis are in the list.\")\n    case _:\n        print(\"Something else is found in the list.\")")
+      expect(tokens[0][0].value).toBe("match");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("points");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("case");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("[");
+      expect(tokens[1][3].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[1][4].value).toBe("]");
+      expect(tokens[1][4].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[1][5].value).toBe(":");
+      expect(tokens[1][5].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[2][0].value).toBe("        ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("print");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[2][2].value).toBe("(");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][3].value).toBe("\"");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][4].value).toBe("No points in the list.");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[2][5].value).toBe("\"");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][6].value).toBe(")");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("case");
+      expect(tokens[3][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("[");
+      expect(tokens[3][3].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[3][4].value).toBe("Point");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[3][5].value).toBe("(");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][6].value).toBe("0");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[3][7].value).toBe(",");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[3][8].value).toBe(" ");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][9].value).toBe("0");
+      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[3][10].value).toBe(")");
+      expect(tokens[3][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][11].value).toBe("]");
+      expect(tokens[3][11].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[3][12].value).toBe(":");
+      expect(tokens[3][12].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[4][0].value).toBe("        ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("print");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[4][2].value).toBe("(");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[4][3].value).toBe("\"");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][4].value).toBe("The origin is the only point in the list.");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[4][5].value).toBe("\"");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][6].value).toBe(")");
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("case");
+      expect(tokens[5][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[5][2].value).toBe(" ");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][3].value).toBe("[");
+      expect(tokens[5][3].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[5][4].value).toBe("Point");
+      expect(tokens[5][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[5][5].value).toBe("(");
+      expect(tokens[5][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[5][6].value).toBe("x");
+      expect(tokens[5][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[5][7].value).toBe(",");
+      expect(tokens[5][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[5][8].value).toBe(" ");
+      expect(tokens[5][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[5][9].value).toBe("y");
+      expect(tokens[5][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[5][10].value).toBe(")");
+      expect(tokens[5][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[5][11].value).toBe("]");
+      expect(tokens[5][11].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[5][12].value).toBe(":");
+      expect(tokens[5][12].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[6][0].value).toBe("        ");
+      expect(tokens[6][0].scopes).toEqual(["source.python"]);
+      expect(tokens[6][1].value).toBe("print");
+      expect(tokens[6][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[6][2].value).toBe("(");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[6][3].value).toBe("f");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[6][4].value).toBe("\"");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[6][5].value).toBe("A single point is in the list.");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[6][6].value).toBe("\"");
+      expect(tokens[6][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[6][7].value).toBe(")");
+      expect(tokens[6][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("case");
+      expect(tokens[7][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[7][2].value).toBe(" ");
+      expect(tokens[7][2].scopes).toEqual(["source.python"]);
+      expect(tokens[7][3].value).toBe("[");
+      expect(tokens[7][3].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[7][4].value).toBe("Point");
+      expect(tokens[7][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[7][5].value).toBe("(");
+      expect(tokens[7][5].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[7][6].value).toBe("0");
+      expect(tokens[7][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[7][7].value).toBe(",");
+      expect(tokens[7][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[7][8].value).toBe(" ");
+      expect(tokens[7][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[7][9].value).toBe("y1");
+      expect(tokens[7][9].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[7][10].value).toBe(")");
+      expect(tokens[7][10].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[7][11].value).toBe(",");
+      expect(tokens[7][11].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[7][12].value).toBe(" ");
+      expect(tokens[7][12].scopes).toEqual(["source.python"]);
+      expect(tokens[7][13].value).toBe("Point");
+      expect(tokens[7][13].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[7][14].value).toBe("(");
+      expect(tokens[7][14].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[7][15].value).toBe("0");
+      expect(tokens[7][15].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","constant.numeric.dec.python"]);
+      expect(tokens[7][16].value).toBe(",");
+      expect(tokens[7][16].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[7][17].value).toBe(" ");
+      expect(tokens[7][17].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[7][18].value).toBe("y2");
+      expect(tokens[7][18].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[7][19].value).toBe(")");
+      expect(tokens[7][19].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[7][20].value).toBe("]");
+      expect(tokens[7][20].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[7][21].value).toBe(":");
+      expect(tokens[7][21].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[8][0].value).toBe("        ");
+      expect(tokens[8][0].scopes).toEqual(["source.python"]);
+      expect(tokens[8][1].value).toBe("print");
+      expect(tokens[8][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[8][2].value).toBe("(");
+      expect(tokens[8][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[8][3].value).toBe("f");
+      expect(tokens[8][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[8][4].value).toBe("\"");
+      expect(tokens[8][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[8][5].value).toBe("Two points on the Y axis are in the list.");
+      expect(tokens[8][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[8][6].value).toBe("\"");
+      expect(tokens[8][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[8][7].value).toBe(")");
+      expect(tokens[8][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[9][0].value).toBe("    ");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].value).toBe("case");
+      expect(tokens[9][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[9][2].value).toBe(" ");
+      expect(tokens[9][2].scopes).toEqual(["source.python"]);
+      expect(tokens[9][3].value).toBe("_");
+      expect(tokens[9][3].scopes).toEqual(["source.python"]);
+      expect(tokens[9][4].value).toBe(":");
+      expect(tokens[9][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[10][0].value).toBe("        ");
+      expect(tokens[10][0].scopes).toEqual(["source.python"]);
+      expect(tokens[10][1].value).toBe("print");
+      expect(tokens[10][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[10][2].value).toBe("(");
+      expect(tokens[10][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[10][3].value).toBe("\"");
+      expect(tokens[10][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[10][4].value).toBe("Something else is found in the list.");
+      expect(tokens[10][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python"]);
+      expect(tokens[10][5].value).toBe("\"");
+      expect(tokens[10][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[10][6].value).toBe(")");
+      expect(tokens[10][6].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/statements/match4.py", 
+    function() {
+      tokens = grammar.tokenizeLines("match point:\n    case Point(x, y) if x == y:\n        print(f\"The point is located on the diagonal Y=X.\")\n    case Point(x, y):\n        print(f\"Point is not on the diagonal.\")")
+      expect(tokens[0][0].value).toBe("match");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("point");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(":");
+      expect(tokens[0][3].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("case");
+      expect(tokens[1][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("Point");
+      expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[1][4].value).toBe("(");
+      expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[1][5].value).toBe("x");
+      expect(tokens[1][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][6].value).toBe(",");
+      expect(tokens[1][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[1][7].value).toBe(" ");
+      expect(tokens[1][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][8].value).toBe("y");
+      expect(tokens[1][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[1][9].value).toBe(")");
+      expect(tokens[1][9].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[1][10].value).toBe(" ");
+      expect(tokens[1][10].scopes).toEqual(["source.python"]);
+      expect(tokens[1][11].value).toBe("if");
+      expect(tokens[1][11].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[1][12].value).toBe(" ");
+      expect(tokens[1][12].scopes).toEqual(["source.python"]);
+      expect(tokens[1][13].value).toBe("x");
+      expect(tokens[1][13].scopes).toEqual(["source.python"]);
+      expect(tokens[1][14].value).toBe(" ");
+      expect(tokens[1][14].scopes).toEqual(["source.python"]);
+      expect(tokens[1][15].value).toBe("==");
+      expect(tokens[1][15].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
+      expect(tokens[1][16].value).toBe(" ");
+      expect(tokens[1][16].scopes).toEqual(["source.python"]);
+      expect(tokens[1][17].value).toBe("y");
+      expect(tokens[1][17].scopes).toEqual(["source.python"]);
+      expect(tokens[1][18].value).toBe(":");
+      expect(tokens[1][18].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[2][0].value).toBe("        ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("print");
+      expect(tokens[2][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[2][2].value).toBe("(");
+      expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[2][3].value).toBe("f");
+      expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][4].value).toBe("\"");
+      expect(tokens[2][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[2][5].value).toBe("The point is located on the diagonal Y=X.");
+      expect(tokens[2][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[2][6].value).toBe("\"");
+      expect(tokens[2][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[2][7].value).toBe(")");
+      expect(tokens[2][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("case");
+      expect(tokens[3][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("Point");
+      expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[3][4].value).toBe("(");
+      expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[3][5].value).toBe("x");
+      expect(tokens[3][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][6].value).toBe(",");
+      expect(tokens[3][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
+      expect(tokens[3][7].value).toBe(" ");
+      expect(tokens[3][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][8].value).toBe("y");
+      expect(tokens[3][8].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
+      expect(tokens[3][9].value).toBe(")");
+      expect(tokens[3][9].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[3][10].value).toBe(":");
+      expect(tokens[3][10].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[4][0].value).toBe("        ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("print");
+      expect(tokens[4][1].scopes).toEqual(["source.python","meta.function-call.python","support.function.builtin.python"]);
+      expect(tokens[4][2].value).toBe("(");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[4][3].value).toBe("f");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[4][4].value).toBe("\"");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[4][5].value).toBe("Point is not on the diagonal.");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[4][6].value).toBe("\"");
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[4][7].value).toBe(")");
+      expect(tokens[4][7].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+    });
+
+  it("test/statements/match5.py", 
+    function() {
+      tokens = grammar.tokenizeLines("match command.split() if command else ['default']:\n    ... # Other cases\n    case [\"north\"] | [\"go\", \"north\"]:\n        ... # handle case\n    case [\"get\", obj] | [\"pick\", \"up\", *other] | [\"pick\", obj, \"up\"]:\n        ... # handle case")
+      expect(tokens[0][0].value).toBe("match");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("command");
+      expect(tokens[0][2].scopes).toEqual(["source.python"]);
+      expect(tokens[0][3].value).toBe(".");
+      expect(tokens[0][3].scopes).toEqual(["source.python","meta.member.access.python","punctuation.separator.period.python"]);
+      expect(tokens[0][4].value).toBe("split");
+      expect(tokens[0][4].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","meta.function-call.generic.python"]);
+      expect(tokens[0][5].value).toBe("(");
+      expect(tokens[0][5].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
+      expect(tokens[0][6].value).toBe(")");
+      expect(tokens[0][6].scopes).toEqual(["source.python","meta.member.access.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("if");
+      expect(tokens[0][8].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][9].value).toBe(" ");
+      expect(tokens[0][9].scopes).toEqual(["source.python"]);
+      expect(tokens[0][10].value).toBe("command");
+      expect(tokens[0][10].scopes).toEqual(["source.python"]);
+      expect(tokens[0][11].value).toBe(" ");
+      expect(tokens[0][11].scopes).toEqual(["source.python"]);
+      expect(tokens[0][12].value).toBe("else");
+      expect(tokens[0][12].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][13].value).toBe(" ");
+      expect(tokens[0][13].scopes).toEqual(["source.python"]);
+      expect(tokens[0][14].value).toBe("[");
+      expect(tokens[0][14].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[0][15].value).toBe("'");
+      expect(tokens[0][15].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][16].value).toBe("default");
+      expect(tokens[0][16].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][17].value).toBe("'");
+      expect(tokens[0][17].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][18].value).toBe("]");
+      expect(tokens[0][18].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[0][19].value).toBe(":");
+      expect(tokens[0][19].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("...");
+      expect(tokens[1][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("#");
+      expect(tokens[1][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][4].value).toBe(" Other cases");
+      expect(tokens[1][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[2][0].value).toBe("    ");
+      expect(tokens[2][0].scopes).toEqual(["source.python"]);
+      expect(tokens[2][1].value).toBe("case");
+      expect(tokens[2][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][2].value).toBe(" ");
+      expect(tokens[2][2].scopes).toEqual(["source.python"]);
+      expect(tokens[2][3].value).toBe("[");
+      expect(tokens[2][3].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[2][4].value).toBe("\"");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][5].value).toBe("north");
+      expect(tokens[2][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][6].value).toBe("\"");
+      expect(tokens[2][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][7].value).toBe("]");
+      expect(tokens[2][7].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[2][8].value).toBe(" ");
+      expect(tokens[2][8].scopes).toEqual(["source.python"]);
+      expect(tokens[2][9].value).toBe("|");
+      expect(tokens[2][9].scopes).toEqual(["source.python","keyword.operator.bitwise.python"]);
+      expect(tokens[2][10].value).toBe(" ");
+      expect(tokens[2][10].scopes).toEqual(["source.python"]);
+      expect(tokens[2][11].value).toBe("[");
+      expect(tokens[2][11].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[2][12].value).toBe("\"");
+      expect(tokens[2][12].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][13].value).toBe("go");
+      expect(tokens[2][13].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][14].value).toBe("\"");
+      expect(tokens[2][14].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][15].value).toBe(",");
+      expect(tokens[2][15].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[2][16].value).toBe(" ");
+      expect(tokens[2][16].scopes).toEqual(["source.python"]);
+      expect(tokens[2][17].value).toBe("\"");
+      expect(tokens[2][17].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][18].value).toBe("north");
+      expect(tokens[2][18].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][19].value).toBe("\"");
+      expect(tokens[2][19].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][20].value).toBe("]");
+      expect(tokens[2][20].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[2][21].value).toBe(":");
+      expect(tokens[2][21].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[3][0].value).toBe("        ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("...");
+      expect(tokens[3][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("#");
+      expect(tokens[3][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][4].value).toBe(" handle case");
+      expect(tokens[3][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[4][0].value).toBe("    ");
+      expect(tokens[4][0].scopes).toEqual(["source.python"]);
+      expect(tokens[4][1].value).toBe("case");
+      expect(tokens[4][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][2].value).toBe(" ");
+      expect(tokens[4][2].scopes).toEqual(["source.python"]);
+      expect(tokens[4][3].value).toBe("[");
+      expect(tokens[4][3].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[4][4].value).toBe("\"");
+      expect(tokens[4][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][5].value).toBe("get");
+      expect(tokens[4][5].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[4][6].value).toBe("\"");
+      expect(tokens[4][6].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][7].value).toBe(",");
+      expect(tokens[4][7].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[4][8].value).toBe(" ");
+      expect(tokens[4][8].scopes).toEqual(["source.python"]);
+      expect(tokens[4][9].value).toBe("obj");
+      expect(tokens[4][9].scopes).toEqual(["source.python"]);
+      expect(tokens[4][10].value).toBe("]");
+      expect(tokens[4][10].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[4][11].value).toBe(" ");
+      expect(tokens[4][11].scopes).toEqual(["source.python"]);
+      expect(tokens[4][12].value).toBe("|");
+      expect(tokens[4][12].scopes).toEqual(["source.python","keyword.operator.bitwise.python"]);
+      expect(tokens[4][13].value).toBe(" ");
+      expect(tokens[4][13].scopes).toEqual(["source.python"]);
+      expect(tokens[4][14].value).toBe("[");
+      expect(tokens[4][14].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[4][15].value).toBe("\"");
+      expect(tokens[4][15].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][16].value).toBe("pick");
+      expect(tokens[4][16].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[4][17].value).toBe("\"");
+      expect(tokens[4][17].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][18].value).toBe(",");
+      expect(tokens[4][18].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[4][19].value).toBe(" ");
+      expect(tokens[4][19].scopes).toEqual(["source.python"]);
+      expect(tokens[4][20].value).toBe("\"");
+      expect(tokens[4][20].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][21].value).toBe("up");
+      expect(tokens[4][21].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[4][22].value).toBe("\"");
+      expect(tokens[4][22].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][23].value).toBe(",");
+      expect(tokens[4][23].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[4][24].value).toBe(" ");
+      expect(tokens[4][24].scopes).toEqual(["source.python"]);
+      expect(tokens[4][25].value).toBe("*");
+      expect(tokens[4][25].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[4][26].value).toBe("other");
+      expect(tokens[4][26].scopes).toEqual(["source.python"]);
+      expect(tokens[4][27].value).toBe("]");
+      expect(tokens[4][27].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[4][28].value).toBe(" ");
+      expect(tokens[4][28].scopes).toEqual(["source.python"]);
+      expect(tokens[4][29].value).toBe("|");
+      expect(tokens[4][29].scopes).toEqual(["source.python","keyword.operator.bitwise.python"]);
+      expect(tokens[4][30].value).toBe(" ");
+      expect(tokens[4][30].scopes).toEqual(["source.python"]);
+      expect(tokens[4][31].value).toBe("[");
+      expect(tokens[4][31].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[4][32].value).toBe("\"");
+      expect(tokens[4][32].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][33].value).toBe("pick");
+      expect(tokens[4][33].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[4][34].value).toBe("\"");
+      expect(tokens[4][34].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][35].value).toBe(",");
+      expect(tokens[4][35].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[4][36].value).toBe(" ");
+      expect(tokens[4][36].scopes).toEqual(["source.python"]);
+      expect(tokens[4][37].value).toBe("obj");
+      expect(tokens[4][37].scopes).toEqual(["source.python"]);
+      expect(tokens[4][38].value).toBe(",");
+      expect(tokens[4][38].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[4][39].value).toBe(" ");
+      expect(tokens[4][39].scopes).toEqual(["source.python"]);
+      expect(tokens[4][40].value).toBe("\"");
+      expect(tokens[4][40].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[4][41].value).toBe("up");
+      expect(tokens[4][41].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[4][42].value).toBe("\"");
+      expect(tokens[4][42].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[4][43].value).toBe("]");
+      expect(tokens[4][43].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[4][44].value).toBe(":");
+      expect(tokens[4][44].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[5][0].value).toBe("        ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("...");
+      expect(tokens[5][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[5][2].value).toBe(" ");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][3].value).toBe("#");
+      expect(tokens[5][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[5][4].value).toBe(" handle case");
+      expect(tokens[5][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/statements/match6.py", 
+    function() {
+      tokens = grammar.tokenizeLines("match (foo + bar):\n    ... # cases\nmatch [foo, bar]:\n    ... # cases\nmatch {foo, bar}:\n    ... # cases")
+      expect(tokens[0][0].value).toBe("match");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("(");
+      expect(tokens[0][2].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
+      expect(tokens[0][3].value).toBe("foo");
+      expect(tokens[0][3].scopes).toEqual(["source.python"]);
+      expect(tokens[0][4].value).toBe(" ");
+      expect(tokens[0][4].scopes).toEqual(["source.python"]);
+      expect(tokens[0][5].value).toBe("+");
+      expect(tokens[0][5].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][6].value).toBe(" ");
+      expect(tokens[0][6].scopes).toEqual(["source.python"]);
+      expect(tokens[0][7].value).toBe("bar");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe(")");
+      expect(tokens[0][8].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
+      expect(tokens[0][9].value).toBe(":");
+      expect(tokens[0][9].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("...");
+      expect(tokens[1][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("#");
+      expect(tokens[1][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][4].value).toBe(" cases");
+      expect(tokens[1][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[2][0].value).toBe("match");
+      expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("[");
+      expect(tokens[2][2].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
+      expect(tokens[2][3].value).toBe("foo");
+      expect(tokens[2][3].scopes).toEqual(["source.python"]);
+      expect(tokens[2][4].value).toBe(",");
+      expect(tokens[2][4].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("bar");
+      expect(tokens[2][6].scopes).toEqual(["source.python"]);
+      expect(tokens[2][7].value).toBe("]");
+      expect(tokens[2][7].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
+      expect(tokens[2][8].value).toBe(":");
+      expect(tokens[2][8].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("...");
+      expect(tokens[3][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("#");
+      expect(tokens[3][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][4].value).toBe(" cases");
+      expect(tokens[3][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[4][0].value).toBe("match");
+      expect(tokens[4][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("{");
+      expect(tokens[4][2].scopes).toEqual(["source.python","punctuation.definition.dict.begin.python"]);
+      expect(tokens[4][3].value).toBe("foo");
+      expect(tokens[4][3].scopes).toEqual(["source.python"]);
+      expect(tokens[4][4].value).toBe(",");
+      expect(tokens[4][4].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
+      expect(tokens[4][5].value).toBe(" ");
+      expect(tokens[4][5].scopes).toEqual(["source.python"]);
+      expect(tokens[4][6].value).toBe("bar");
+      expect(tokens[4][6].scopes).toEqual(["source.python"]);
+      expect(tokens[4][7].value).toBe("}");
+      expect(tokens[4][7].scopes).toEqual(["source.python","punctuation.definition.dict.end.python"]);
+      expect(tokens[4][8].value).toBe(":");
+      expect(tokens[4][8].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("...");
+      expect(tokens[5][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[5][2].value).toBe(" ");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][3].value).toBe("#");
+      expect(tokens[5][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[5][4].value).toBe(" cases");
+      expect(tokens[5][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
+  it("test/statements/match7.py", 
+    function() {
+      tokens = grammar.tokenizeLines("match 'prefix' + foo:\n    ... # cases\nmatch \"prefix\" + foo:\n    ... # cases\nmatch f'prefix{foo}':\n    ... # cases\nmatch f\"prefix{foo}\":\n    ... # cases\nmatch -foo:\n    ... # cases\nmatch not foo:\n    ... # cases")
+      expect(tokens[0][0].value).toBe("match");
+      expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[0][1].value).toBe(" ");
+      expect(tokens[0][1].scopes).toEqual(["source.python"]);
+      expect(tokens[0][2].value).toBe("'");
+      expect(tokens[0][2].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[0][3].value).toBe("prefix");
+      expect(tokens[0][3].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[0][4].value).toBe("'");
+      expect(tokens[0][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[0][5].value).toBe(" ");
+      expect(tokens[0][5].scopes).toEqual(["source.python"]);
+      expect(tokens[0][6].value).toBe("+");
+      expect(tokens[0][6].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[0][7].value).toBe(" ");
+      expect(tokens[0][7].scopes).toEqual(["source.python"]);
+      expect(tokens[0][8].value).toBe("foo");
+      expect(tokens[0][8].scopes).toEqual(["source.python"]);
+      expect(tokens[0][9].value).toBe(":");
+      expect(tokens[0][9].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[1][0].value).toBe("    ");
+      expect(tokens[1][0].scopes).toEqual(["source.python"]);
+      expect(tokens[1][1].value).toBe("...");
+      expect(tokens[1][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[1][2].value).toBe(" ");
+      expect(tokens[1][2].scopes).toEqual(["source.python"]);
+      expect(tokens[1][3].value).toBe("#");
+      expect(tokens[1][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[1][4].value).toBe(" cases");
+      expect(tokens[1][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[2][0].value).toBe("match");
+      expect(tokens[2][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[2][1].value).toBe(" ");
+      expect(tokens[2][1].scopes).toEqual(["source.python"]);
+      expect(tokens[2][2].value).toBe("\"");
+      expect(tokens[2][2].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
+      expect(tokens[2][3].value).toBe("prefix");
+      expect(tokens[2][3].scopes).toEqual(["source.python","string.quoted.single.python"]);
+      expect(tokens[2][4].value).toBe("\"");
+      expect(tokens[2][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
+      expect(tokens[2][5].value).toBe(" ");
+      expect(tokens[2][5].scopes).toEqual(["source.python"]);
+      expect(tokens[2][6].value).toBe("+");
+      expect(tokens[2][6].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[2][7].value).toBe(" ");
+      expect(tokens[2][7].scopes).toEqual(["source.python"]);
+      expect(tokens[2][8].value).toBe("foo");
+      expect(tokens[2][8].scopes).toEqual(["source.python"]);
+      expect(tokens[2][9].value).toBe(":");
+      expect(tokens[2][9].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[3][0].value).toBe("    ");
+      expect(tokens[3][0].scopes).toEqual(["source.python"]);
+      expect(tokens[3][1].value).toBe("...");
+      expect(tokens[3][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[3][2].value).toBe(" ");
+      expect(tokens[3][2].scopes).toEqual(["source.python"]);
+      expect(tokens[3][3].value).toBe("#");
+      expect(tokens[3][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[3][4].value).toBe(" cases");
+      expect(tokens[3][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[4][0].value).toBe("match");
+      expect(tokens[4][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[4][1].value).toBe(" ");
+      expect(tokens[4][1].scopes).toEqual(["source.python"]);
+      expect(tokens[4][2].value).toBe("f");
+      expect(tokens[4][2].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[4][3].value).toBe("'");
+      expect(tokens[4][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[4][4].value).toBe("prefix");
+      expect(tokens[4][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[4][5].value).toBe("{");
+      expect(tokens[4][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[4][6].value).toBe("foo");
+      expect(tokens[4][6].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[4][7].value).toBe("}");
+      expect(tokens[4][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[4][8].value).toBe("'");
+      expect(tokens[4][8].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[4][9].value).toBe(":");
+      expect(tokens[4][9].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[5][0].value).toBe("    ");
+      expect(tokens[5][0].scopes).toEqual(["source.python"]);
+      expect(tokens[5][1].value).toBe("...");
+      expect(tokens[5][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[5][2].value).toBe(" ");
+      expect(tokens[5][2].scopes).toEqual(["source.python"]);
+      expect(tokens[5][3].value).toBe("#");
+      expect(tokens[5][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[5][4].value).toBe(" cases");
+      expect(tokens[5][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[6][0].value).toBe("match");
+      expect(tokens[6][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[6][1].value).toBe(" ");
+      expect(tokens[6][1].scopes).toEqual(["source.python"]);
+      expect(tokens[6][2].value).toBe("f");
+      expect(tokens[6][2].scopes).toEqual(["source.python","meta.fstring.python","storage.type.string.python string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[6][3].value).toBe("\"");
+      expect(tokens[6][3].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.begin.python"]);
+      expect(tokens[6][4].value).toBe("prefix");
+      expect(tokens[6][4].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python"]);
+      expect(tokens[6][5].value).toBe("{");
+      expect(tokens[6][5].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[6][6].value).toBe("foo");
+      expect(tokens[6][6].scopes).toEqual(["source.python","meta.fstring.python"]);
+      expect(tokens[6][7].value).toBe("}");
+      expect(tokens[6][7].scopes).toEqual(["source.python","meta.fstring.python","constant.character.format.placeholder.other.python"]);
+      expect(tokens[6][8].value).toBe("\"");
+      expect(tokens[6][8].scopes).toEqual(["source.python","meta.fstring.python","string.quoted.single.python string.interpolated.python punctuation.definition.string.end.python"]);
+      expect(tokens[6][9].value).toBe(":");
+      expect(tokens[6][9].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[7][0].value).toBe("    ");
+      expect(tokens[7][0].scopes).toEqual(["source.python"]);
+      expect(tokens[7][1].value).toBe("...");
+      expect(tokens[7][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[7][2].value).toBe(" ");
+      expect(tokens[7][2].scopes).toEqual(["source.python"]);
+      expect(tokens[7][3].value).toBe("#");
+      expect(tokens[7][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[7][4].value).toBe(" cases");
+      expect(tokens[7][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[8][0].value).toBe("match");
+      expect(tokens[8][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[8][1].value).toBe(" ");
+      expect(tokens[8][1].scopes).toEqual(["source.python"]);
+      expect(tokens[8][2].value).toBe("-");
+      expect(tokens[8][2].scopes).toEqual(["source.python","keyword.operator.arithmetic.python"]);
+      expect(tokens[8][3].value).toBe("foo");
+      expect(tokens[8][3].scopes).toEqual(["source.python"]);
+      expect(tokens[8][4].value).toBe(":");
+      expect(tokens[8][4].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[9][0].value).toBe("    ");
+      expect(tokens[9][0].scopes).toEqual(["source.python"]);
+      expect(tokens[9][1].value).toBe("...");
+      expect(tokens[9][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[9][2].value).toBe(" ");
+      expect(tokens[9][2].scopes).toEqual(["source.python"]);
+      expect(tokens[9][3].value).toBe("#");
+      expect(tokens[9][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[9][4].value).toBe(" cases");
+      expect(tokens[9][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+      expect(tokens[10][0].value).toBe("match");
+      expect(tokens[10][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
+      expect(tokens[10][1].value).toBe(" ");
+      expect(tokens[10][1].scopes).toEqual(["source.python"]);
+      expect(tokens[10][2].value).toBe("not");
+      expect(tokens[10][2].scopes).toEqual(["source.python","keyword.operator.logical.python"]);
+      expect(tokens[10][3].value).toBe(" ");
+      expect(tokens[10][3].scopes).toEqual(["source.python"]);
+      expect(tokens[10][4].value).toBe("foo");
+      expect(tokens[10][4].scopes).toEqual(["source.python"]);
+      expect(tokens[10][5].value).toBe(":");
+      expect(tokens[10][5].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
+      expect(tokens[11][0].value).toBe("    ");
+      expect(tokens[11][0].scopes).toEqual(["source.python"]);
+      expect(tokens[11][1].value).toBe("...");
+      expect(tokens[11][1].scopes).toEqual(["source.python","constant.other.ellipsis.python"]);
+      expect(tokens[11][2].value).toBe(" ");
+      expect(tokens[11][2].scopes).toEqual(["source.python"]);
+      expect(tokens[11][3].value).toBe("#");
+      expect(tokens[11][3].scopes).toEqual(["source.python","comment.line.number-sign.python","punctuation.definition.comment.python"]);
+      expect(tokens[11][4].value).toBe(" cases");
+      expect(tokens[11][4].scopes).toEqual(["source.python","comment.line.number-sign.python"]);
+    });
+
   it("test/statements/nonlocal1.py", 
     function() {
       tokens = grammar.tokenizeLines("nonlocal a, b, c")
diff --git a/test/builtins/builtins3.py b/test/builtins/builtins3.py
index 181eacd1..f1f90d9c 100644
--- a/test/builtins/builtins3.py
+++ b/test/builtins/builtins3.py
@@ -40,6 +40,9 @@
 some.__prepare__
 some.__package__
 some.__traceback__
+some.__closure__
+some.__globals__
+some.__match_args__
 some.__notspecial__
 
 
@@ -183,4 +186,13 @@
 __traceback__ : meta.member.access.python, source.python, support.variable.magic.python
 some          : source.python
 .             : meta.member.access.python, punctuation.separator.period.python, source.python
+__closure__   : meta.member.access.python, source.python, support.variable.magic.python
+some          : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__globals__   : meta.member.access.python, source.python, support.variable.magic.python
+some          : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+__match_args__ : meta.member.access.python, source.python, support.variable.magic.python
+some          : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
 __notspecial__ : meta.attribute.python, meta.member.access.python, source.python
diff --git a/test/builtins/builtins7.py b/test/builtins/builtins7.py
index eb02d7fb..6d23b2b7 100644
--- a/test/builtins/builtins7.py
+++ b/test/builtins/builtins7.py
@@ -1,4 +1,6 @@
 breakpoint()
+aiter()
+anext()
 
 
 
@@ -6,3 +8,9 @@
 breakpoint    : meta.function-call.python, source.python, support.function.builtin.python
 (             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
 )             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+aiter         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+anext         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/classes/class9.py b/test/classes/class9.py
index bbf24feb..a4ea943f 100644
--- a/test/classes/class9.py
+++ b/test/classes/class9.py
@@ -1,5 +1,6 @@
 class Foo:
     __slots__ = ()
+    __match_args__ = ('key', 'name')
 
 
 
@@ -13,4 +14,19 @@ class         : meta.class.python, source.python, storage.type.class.python
 =             : keyword.operator.assignment.python, source.python
               : source.python
 (             : punctuation.parenthesis.begin.python, source.python
+)             : punctuation.parenthesis.end.python, source.python
+              : source.python
+__match_args__ : source.python, support.variable.magic.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+(             : punctuation.parenthesis.begin.python, source.python
+'             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+key           : source.python, string.quoted.single.python
+'             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+'             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+name          : source.python, string.quoted.single.python
+'             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
 )             : punctuation.parenthesis.end.python, source.python
diff --git a/test/expressions/expr22.py b/test/expressions/expr22.py
new file mode 100644
index 00000000..7c03f542
--- /dev/null
+++ b/test/expressions/expr22.py
@@ -0,0 +1,33 @@
+match = 13
+case = 12
+if case == 4:
+  return match * 5
+
+
+
+match         : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+13            : constant.numeric.dec.python, source.python
+case          : source.python
+              : source.python
+=             : keyword.operator.assignment.python, source.python
+              : source.python
+12            : constant.numeric.dec.python, source.python
+if            : keyword.control.flow.python, source.python
+              : source.python
+case          : source.python
+              : source.python
+==            : keyword.operator.comparison.python, source.python
+              : source.python
+4             : constant.numeric.dec.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+return        : keyword.control.flow.python, source.python
+              : source.python
+match         : source.python
+              : source.python
+*             : keyword.operator.arithmetic.python, source.python
+              : source.python
+5             : constant.numeric.dec.python, source.python
diff --git a/test/expressions/special2.py b/test/expressions/special2.py
index 2f360985..727d664f 100644
--- a/test/expressions/special2.py
+++ b/test/expressions/special2.py
@@ -7,7 +7,7 @@ def __class_getitem__(): pass
 __post_init__ : source.python, support.variable.magic.python
 def           : meta.function.python, source.python, storage.type.function.python
               : meta.function.python, source.python
-__class_getitem__ : meta.function.python, source.python, support.variable.magic.python
+__class_getitem__ : meta.function.python, source.python, support.function.magic.python
 (             : meta.function.parameters.python, meta.function.python, punctuation.definition.parameters.begin.python, source.python
 )             : meta.function.parameters.python, meta.function.python, punctuation.definition.parameters.end.python, source.python
 :             : meta.function.python, punctuation.section.function.begin.python, source.python
diff --git a/test/statements/match1.py b/test/statements/match1.py
new file mode 100644
index 00000000..f393066a
--- /dev/null
+++ b/test/statements/match1.py
@@ -0,0 +1,61 @@
+def foo(status):
+    match status:
+        case 404:
+            return "Not found"
+        case 401 | 403:
+            return "Not allowed"
+        case _:
+            return "Something's wrong with the internet"
+
+
+
+
+def           : meta.function.python, source.python, storage.type.function.python
+              : meta.function.python, source.python
+foo           : entity.name.function.python, meta.function.python, source.python
+(             : meta.function.parameters.python, meta.function.python, punctuation.definition.parameters.begin.python, source.python
+status        : meta.function.parameters.python, meta.function.python, source.python, variable.parameter.function.language.python
+)             : meta.function.parameters.python, meta.function.python, punctuation.definition.parameters.end.python, source.python
+:             : meta.function.python, punctuation.section.function.begin.python, source.python
+              : source.python
+match         : keyword.control.flow.python, source.python
+              : source.python
+status        : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+404           : constant.numeric.dec.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+return        : keyword.control.flow.python, source.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+Not found     : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+401           : constant.numeric.dec.python, source.python
+              : source.python
+|             : keyword.operator.bitwise.python, source.python
+              : source.python
+403           : constant.numeric.dec.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+return        : keyword.control.flow.python, source.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+Not allowed   : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+_             : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+return        : keyword.control.flow.python, source.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+Something's wrong with the internet : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
diff --git a/test/statements/match2.py b/test/statements/match2.py
new file mode 100644
index 00000000..a88ba055
--- /dev/null
+++ b/test/statements/match2.py
@@ -0,0 +1,112 @@
+match point:
+    case Point(x=0, y=0):
+        print("Origin is the point's location.")
+    case Point(x=0, y=y):
+        print(f"The point is on the y-axis.")
+    case Point(x=x, y=0):
+        print(f"The point is on the x-axis.")
+    case Point():
+        print("The point is located somewhere else on the plane.")
+    case _:
+        print("Not a point")
+
+
+
+match         : keyword.control.flow.python, source.python
+              : source.python
+point         : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+Point         : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+x             : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+0             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+y             : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+0             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+Origin is the point's location. : meta.function-call.arguments.python, meta.function-call.python, source.python, string.quoted.single.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+Point         : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+x             : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+0             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+y             : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+y             : meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+f             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
+The point is on the y-axis. : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+Point         : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+x             : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+x             : meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+y             : meta.function-call.arguments.python, meta.function-call.python, source.python, variable.parameter.function-call.python
+=             : keyword.operator.assignment.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+0             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+f             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
+The point is on the x-axis. : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+Point         : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+The point is located somewhere else on the plane. : meta.function-call.arguments.python, meta.function-call.python, source.python, string.quoted.single.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+_             : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+Not a point   : meta.function-call.arguments.python, meta.function-call.python, source.python, string.quoted.single.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/statements/match3.py b/test/statements/match3.py
new file mode 100644
index 00000000..ac8e176c
--- /dev/null
+++ b/test/statements/match3.py
@@ -0,0 +1,114 @@
+match points:
+    case []:
+        print("No points in the list.")
+    case [Point(0, 0)]:
+        print("The origin is the only point in the list.")
+    case [Point(x, y)]:
+        print(f"A single point is in the list.")
+    case [Point(0, y1), Point(0, y2)]:
+        print(f"Two points on the Y axis are in the list.")
+    case _:
+        print("Something else is found in the list.")
+
+
+
+match         : keyword.control.flow.python, source.python
+              : source.python
+points        : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+]             : punctuation.definition.list.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+No points in the list. : meta.function-call.arguments.python, meta.function-call.python, source.python, string.quoted.single.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+Point         : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+0             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+0             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+]             : punctuation.definition.list.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+The origin is the only point in the list. : meta.function-call.arguments.python, meta.function-call.python, source.python, string.quoted.single.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+Point         : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+x             : meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+y             : meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+]             : punctuation.definition.list.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+f             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
+A single point is in the list. : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+Point         : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+0             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+y1            : meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+Point         : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+0             : constant.numeric.dec.python, meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+y2            : meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+]             : punctuation.definition.list.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+f             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
+Two points on the Y axis are in the list. : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+_             : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+Something else is found in the list. : meta.function-call.arguments.python, meta.function-call.python, source.python, string.quoted.single.python
+"             : meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/statements/match4.py b/test/statements/match4.py
new file mode 100644
index 00000000..fc4857f5
--- /dev/null
+++ b/test/statements/match4.py
@@ -0,0 +1,59 @@
+match point:
+    case Point(x, y) if x == y:
+        print(f"The point is located on the diagonal Y=X.")
+    case Point(x, y):
+        print(f"Point is not on the diagonal.")
+
+
+
+
+match         : keyword.control.flow.python, source.python
+              : source.python
+point         : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+Point         : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+x             : meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+y             : meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+if            : keyword.control.flow.python, source.python
+              : source.python
+x             : source.python
+              : source.python
+==            : keyword.operator.comparison.python, source.python
+              : source.python
+y             : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+f             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
+The point is located on the diagonal Y=X. : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+Point         : meta.function-call.generic.python, meta.function-call.python, source.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+x             : meta.function-call.arguments.python, meta.function-call.python, source.python
+,             : meta.function-call.arguments.python, meta.function-call.python, punctuation.separator.arguments.python, source.python
+              : meta.function-call.arguments.python, meta.function-call.python, source.python
+y             : meta.function-call.arguments.python, meta.function-call.python, source.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+print         : meta.function-call.python, source.python, support.function.builtin.python
+(             : meta.function-call.python, punctuation.definition.arguments.begin.python, source.python
+f             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
+Point is not on the diagonal. : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, source.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, meta.function-call.arguments.python, meta.function-call.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
+)             : meta.function-call.python, punctuation.definition.arguments.end.python, source.python
diff --git a/test/statements/match5.py b/test/statements/match5.py
new file mode 100644
index 00000000..905ef8ba
--- /dev/null
+++ b/test/statements/match5.py
@@ -0,0 +1,112 @@
+match command.split() if command else ['default']:
+    ... # Other cases
+    case ["north"] | ["go", "north"]:
+        ... # handle case
+    case ["get", obj] | ["pick", "up", *other] | ["pick", obj, "up"]:
+        ... # handle case
+
+
+
+
+match         : keyword.control.flow.python, source.python
+              : source.python
+command       : source.python
+.             : meta.member.access.python, punctuation.separator.period.python, source.python
+split         : meta.function-call.generic.python, meta.function-call.python, meta.member.access.python, source.python
+(             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.begin.python, source.python
+)             : meta.function-call.python, meta.member.access.python, punctuation.definition.arguments.end.python, source.python
+              : source.python
+if            : keyword.control.flow.python, source.python
+              : source.python
+command       : source.python
+              : source.python
+else          : keyword.control.flow.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+'             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+default       : source.python, string.quoted.single.python
+'             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+]             : punctuation.definition.list.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ Other cases  : comment.line.number-sign.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+north         : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+]             : punctuation.definition.list.end.python, source.python
+              : source.python
+|             : keyword.operator.bitwise.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+go            : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+north         : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+]             : punctuation.definition.list.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ handle case  : comment.line.number-sign.python, source.python
+              : source.python
+case          : keyword.control.flow.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+get           : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+obj           : source.python
+]             : punctuation.definition.list.end.python, source.python
+              : source.python
+|             : keyword.operator.bitwise.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+pick          : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+up            : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+*             : keyword.operator.arithmetic.python, source.python
+other         : source.python
+]             : punctuation.definition.list.end.python, source.python
+              : source.python
+|             : keyword.operator.bitwise.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+pick          : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+obj           : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+up            : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+]             : punctuation.definition.list.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ handle case  : comment.line.number-sign.python, source.python
diff --git a/test/statements/match6.py b/test/statements/match6.py
new file mode 100644
index 00000000..b74491f7
--- /dev/null
+++ b/test/statements/match6.py
@@ -0,0 +1,53 @@
+match (foo + bar):
+    ... # cases
+match [foo, bar]:
+    ... # cases
+match {foo, bar}:
+    ... # cases
+
+
+
+
+match         : keyword.control.flow.python, source.python
+              : source.python
+(             : punctuation.parenthesis.begin.python, source.python
+foo           : source.python
+              : source.python
++             : keyword.operator.arithmetic.python, source.python
+              : source.python
+bar           : source.python
+)             : punctuation.parenthesis.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ cases        : comment.line.number-sign.python, source.python
+match         : keyword.control.flow.python, source.python
+              : source.python
+[             : punctuation.definition.list.begin.python, source.python
+foo           : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+bar           : source.python
+]             : punctuation.definition.list.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ cases        : comment.line.number-sign.python, source.python
+match         : keyword.control.flow.python, source.python
+              : source.python
+{             : punctuation.definition.dict.begin.python, source.python
+foo           : source.python
+,             : punctuation.separator.element.python, source.python
+              : source.python
+bar           : source.python
+}             : punctuation.definition.dict.end.python, source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ cases        : comment.line.number-sign.python, source.python
\ No newline at end of file
diff --git a/test/statements/match7.py b/test/statements/match7.py
new file mode 100644
index 00000000..878fa813
--- /dev/null
+++ b/test/statements/match7.py
@@ -0,0 +1,97 @@
+match 'prefix' + foo:
+    ... # cases
+match "prefix" + foo:
+    ... # cases
+match f'prefix{foo}':
+    ... # cases
+match f"prefix{foo}":
+    ... # cases
+match -foo:
+    ... # cases
+match not foo:
+    ... # cases
+
+
+
+
+match         : keyword.control.flow.python, source.python
+              : source.python
+'             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+prefix        : source.python, string.quoted.single.python
+'             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+              : source.python
++             : keyword.operator.arithmetic.python, source.python
+              : source.python
+foo           : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ cases        : comment.line.number-sign.python, source.python
+match         : keyword.control.flow.python, source.python
+              : source.python
+"             : punctuation.definition.string.begin.python, source.python, string.quoted.single.python
+prefix        : source.python, string.quoted.single.python
+"             : punctuation.definition.string.end.python, source.python, string.quoted.single.python
+              : source.python
++             : keyword.operator.arithmetic.python, source.python
+              : source.python
+foo           : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ cases        : comment.line.number-sign.python, source.python
+match         : keyword.control.flow.python, source.python
+              : source.python
+f             : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
+'             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
+prefix        : meta.fstring.python, source.python, string.interpolated.python, string.quoted.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+foo           : meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+'             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ cases        : comment.line.number-sign.python, source.python
+match         : keyword.control.flow.python, source.python
+              : source.python
+f             : meta.fstring.python, source.python, storage.type.string.python, string.interpolated.python, string.quoted.single.python
+"             : meta.fstring.python, punctuation.definition.string.begin.python, source.python, string.interpolated.python, string.quoted.single.python
+prefix        : meta.fstring.python, source.python, string.interpolated.python, string.quoted.single.python
+{             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+foo           : meta.fstring.python, source.python
+}             : constant.character.format.placeholder.other.python, meta.fstring.python, source.python
+"             : meta.fstring.python, punctuation.definition.string.end.python, source.python, string.interpolated.python, string.quoted.single.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ cases        : comment.line.number-sign.python, source.python
+match         : keyword.control.flow.python, source.python
+              : source.python
+-             : keyword.operator.arithmetic.python, source.python
+foo           : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ cases        : comment.line.number-sign.python, source.python
+match         : keyword.control.flow.python, source.python
+              : source.python
+not           : keyword.operator.logical.python, source.python
+              : source.python
+foo           : source.python
+:             : punctuation.separator.colon.python, source.python
+              : source.python
+...           : constant.other.ellipsis.python, source.python
+              : source.python
+#             : comment.line.number-sign.python, punctuation.definition.comment.python, source.python
+ cases        : comment.line.number-sign.python, source.python
\ No newline at end of file