anchor.diff:          +cell match 0 or 1 times
           +cell optional, max one
   
  -p
  -    |  There are no nested or scoped quantifiers. You can build those
  -    |  behaviours with #[code on_match] callbacks.
  ++h(3, "quantifiers-example1") Quantifiers example: Using linguistic annotations
  +
  +p
  +    |  Let's say you're analysing user comments and you want to find out what
  +    |  people are saying about Facebook. You want to start off by finding
  +    |  adjectives following "Facebook is" or "Facebook was". This is obviously
  +    |  a very rudimentary solution, but it'll be fast, and a great way get an
  +    |  idea for what's in your data. Your pattern could look like this:
  +
  ++code.
  +    [{'LOWER': 'facebook'}, {'LEMMA': 'be'}, {'POS': 'ADV', 'OP': '*'}, {'POS': 'ADJ'}]
  +
  +p
  +    |  This translates to a token whose lowercase form matches "facebook"
  +    |  (like Facebook, facebook or FACEBOOK), followed by a token with the lemma
  +    |  "be" (for example, is, was, or 's), followed by an #[strong optional] adverb,
  +    |  followed by an adjective. Using the linguistic annotations here is
  +    |  especially useful, because you can tell spaCy to match "Facebook's
  +    |  annoying", but #[strong not] "Facebook's annoying ads". The optional
  +    |  adverb makes sure you won't miss adjectives with intensifiers, like
  +    |  "pretty awful" or "very nice".
  +
  +p
  +    |  To get a quick overview of the results, you could collect all sentences
  +    |  containing a match and render them with the
  +    |  #[+a("/docs/usage/visualizers") displaCy visualizer].
  +    |  In the callback function, you'll have access to the #[code start] and
  +    |  #[code end] of each match, as well as the parent #[code Doc]. This lets
  +    |  you determine the sentence containing the match,
  +    |  #[code doc[start : end].sent], and calculate the start and end of the
  +    |  matched span within the sentence. Using displaCy in
  +    |  #[+a("/docs/usage/visualizers#manual-usage") "manual" mode] lets you
  +    |  pass in a list of dictionaries containing the text and entities to render.
  +
  ++code.
  +    from spacy import displacy
  +    from spacy.matcher import Matcher
  +
  +    nlp = spacy.load('en')
  +    matcher = Matcher(nlp.vocab)
  +    matched_sents = [] # collect data of matched sentences to be visualized
  +
  +    def collect_sents(matcher, doc, i, matches):
  +        match_id, start, end = matches[i]
  +        span = doc[start : end] # matched span
  +        sent = span.sent # sentence containing matched span
  +        # append mock entity for match in displaCy style to matched_sents
  +        # get the match span by ofsetting the start and end of the span with the
  +        # start and end of the sentence in the doc
  +        match_ents = [{'start': span.start-sent.start, 'end': span.end-sent.start,
  +                       'label': 'MATCH'}]
  +        matched_sents.append({'text': sent.text, 'ents': match_ents })
  +
  +    pattern = [{'LOWER': 'facebook'}, {'LEMMA': 'be'}, {'POS': 'ADV', 'OP': '*'},
  +               {'POS': 'ADJ'}]
  +    matcher.add('FacebookIs', collect_sents, pattern) # add pattern
  +    matches = matcher(nlp(LOTS_OF_TEXT)) # match on your text
  +
  +    # serve visualization of sentences containing match with displaCy
  +    # set manual=True to make displaCy render straight from a dictionary
  +    displacy.serve(matched_sents, style='ent', manual=True)
  +
  +
  ++h(3, "quantifiers-example2") Quantifiers example: Phone numbers
  +
  +p
  +    |  Phone numbers can have many different formats and matching them is often
  +    |  tricky. During tokenization, spaCy will leave sequences of numbers intact
  +    |  and only split on whitespace and punctuation. This means that your match
  +    |  pattern will have to look out for number sequences of a certain length,
  +    |  surrounded by specific punctuation – depending on the
  +    |  #[+a("https://en.wikipedia.org/wiki/National_conventions_for_writing_telephone_numbers") national conventions].
  +
  +p
  +    |  The #[code IS_DIGIT] flag is not very helpful here, because it doesn't
  +    |  tell us anything about the length. However, you can use the #[code SHAPE]
  +    |  flag, with each #[code d] representing a digit:
  +
  ++code.
  +    [{'ORTH': '('}, {'SHAPE': 'ddd'}, {'ORTH': ')'}, {'SHAPE': 'dddd'},
  +     {'ORTH': '-', 'OP': '?'}, {'SHAPE': 'dddd'}]
  +
  +p
  +    |  This will match phone numbers of the format #[strong (123) 4567 8901] or
  +    |  #[strong (123) 4567-8901]. To also match formats like #[strong (123) 456 789],
  +    |  you can add a second pattern using #[code 'ddd'] in place of #[code 'dddd'].
  +    |  By hard-coding some values, you can match only certain, country-specific
  +    |  numbers. For example, here's a pattern to match the most common formats of
  +    |  #[+a("https://en.wikipedia.org/wiki/National_conventions_for_writing_telephone_numbers#Germany") international German numbers]:
  +
  ++code.
  +    [{'ORTH': '+'}, {'ORTH': '49'}, {'ORTH': '(', 'OP': '?'}, {'SHAPE': 'dddd'},
  +     {'ORTH': ')', 'OP': '?'}, {'SHAPE': 'dddddd'}]
  +
  +p
  +    |  Depending on the formats your application needs to match, creating an
  +    |  extensive set of rules like this is often better than training a model.
  +    |  It'll produce more predictable results, is much easier to modify and
  +    |  extend, and doesn't require any training data – only a set of
  +    |  test cases.
  
positive.code:         span.merge(is_stop=True) # merge (and mark it as a stop word, just in case)
          span.set_flag(BAD_HTML_FLAG, True) # set BAD_HTML_FLAG
  
  +aside("Tip: Visualizing matches")
      |  When working with entities, you can use #[+api("displacy") displaCy]
      |  to quickly generate a NER visualization from your updated #[code Doc],
  
negative.code:         # Append entity to the doc's entity. (Don't overwrite doc.ents!)
          match_id, start, end = matches[i]
          doc.ents += ((EVENT, start, end),)
  
      matcher.add('GoogleIO', on_match=add_event_ent,
                  [{'ORTH': 'Google'}, {'UPPER': 'I'}, {'ORTH': '/'}, {'UPPER': 'O'}],
                  [{'ORTH': 'Google'}, {'UPPER': 'I'}, {'ORTH': '/'}, {'UPPER': 'O'}, {'IS_DIGIT': True}])
  
  p
      |  In addition to mentions of "Google I/O", your data also contains some
  