
Hi Bernie,
Actually an IParser can do anything it wants. The only requirements of a parser are that it returns some sort of parse data that gets set to the document's ParseData property. Sometimes parsers do want to reuse the ILexer set up for the language. In these scenarios, yes you can use an ITextSnapshotReader. Alternatively the request passes you an ITextBufferReader instance in its TextBufferReader property. That is a low-level text scanner that can be used if you have a custom lexer that should be used to feed tokens to your parser instead.
The ILexer and related token tagger provider services registered with a language are really only used to drive classification (and viat that, syntax highlighting), along with feeding tokens to ITextSnapshotReader instances. Token taggers store data to enable incremental lexing, meaning being able to pick up lexing at a certain point in the document instead of always at the start. By using that sort of feature along with various virtualization techniques we use, our text renders super-fast in editor views and can open huge documents like 10MB about instantly.
As mentioned above IParser instances can choose to use an ITextSnapshotReader, which indirectly have them using the ILexer and token tagger. Or other times they may create their own lexer that was generated using some third-party parser generator instead. That is why we supply the request.TextBufferReader, so that a low level text stream can be passed to third-party lexers as needed.
As far as sequencing, when text changes occur, views are notified of the change. They will request that dirty regions have their tokens rescanned with the ILexer so that classifications and syntax highlighting can be updated. This occurs right in the main UI thread and goes fast since we only lex through what is visible in the view.
If you are using a parse request dispatcher (to enabled worker threads for parsing), the parser is called in a worker thread following a short delay after any text change occurs. The text change could be document load, typing, or anything else. The parser will always be called after a delay and in the scenario where many text changes are occuring quickly in a row (like while typing), it will delay subsequent parser calls until a brief idle period has been reached. When the parser completes, it returns its result back to the document.ParseData property and the ParseDataChanged event fires.
You shouldn't need to worry about having to call one phase before another. Just let the text/parsing framework do its thing and you should get the right results regardless of how things get called.
Hope that helps.