14 using System.Collections.Generic;
15 using System.Globalization;
25 #region Properties and Fields: Data, _source
39 #region Scanning tokens
42 if(Context.BufferedTokens.Count > 0) {
43 Context.CurrentToken = Context.BufferedTokens.Pop();
61 private void ScanToken() {
62 if (!MatchNonGrammarTerminals() && !MatchRegularTerminals()) {
66 var token = Context.CurrentToken;
68 if (token != null && !token.IsError()) {
70 SourceStream.PreviewPosition = SourceStream.Location.Position + token.Length;
71 SourceStream.MoveLocationToPreviewPosition();
80 private bool MatchNonGrammarTerminals() {
82 if (!Data.NonGrammarTerminalsLookup.TryGetValue(SourceStream.PreviewChar, out terms))
84 foreach(var term
in terms) {
85 SourceStream.ResetPreviewPosition();
86 Context.CurrentToken = term.TryMatch(Context, SourceStream);
87 if (Context.CurrentToken != null)
88 term.InvokeValidateToken(Context);
89 if (Context.CurrentToken != null) {
92 var token = Context.CurrentToken;
93 if (token.Category ==
TokenCategory.Content && NeedLineStartToken(token.Location)) {
94 Context.BufferedTokens.Push(token);
95 SourceStream.Location = token.Location;
96 Context.CurrentToken = SourceStream.CreateToken(Grammar.LineStartTerminal);
97 Context.PreviousLineStart = SourceStream.Location;
102 SourceStream.ResetPreviewPosition();
106 private bool NeedLineStartToken(SourceLocation forLocation) {
107 return Grammar.FlagIsSet(LanguageFlags.EmitLineStartToken) && forLocation.Line > Context.PreviousLineStart.Line;
110 private bool MatchRegularTerminals() {
114 if (NeedLineStartToken(SourceStream.Location)) {
115 Context.CurrentToken = SourceStream.CreateToken(Grammar.LineStartTerminal);
116 Context.PreviousLineStart = SourceStream.Location;
121 ComputeCurrentTerminals();
123 if (Context.CurrentTerminals.Count > 1)
124 Grammar.OnScannerSelectTerminal(Context);
128 if (Context.CurrentToken == null)
129 Context.CurrentToken = Grammar.TryMatch(Context, SourceStream);
130 if (Context.CurrentToken is MultiToken)
132 return Context.CurrentToken != null;
139 private bool MatchAllTerminals() {
140 Context.CurrentTerminals.Clear();
141 Context.CurrentTerminals.AddRange(Data.Language.GrammarData.Terminals);
143 if (Context.CurrentToken is MultiToken)
145 return Context.CurrentToken != null;
149 private void UnpackMultiToken() {
150 var mtoken = Context.CurrentToken as MultiToken;
151 if (mtoken == null)
return;
152 for (
int i = mtoken.ChildTokens.Count-1; i >= 0; i--)
153 Context.BufferedTokens.Push(mtoken.ChildTokens[i]);
154 Context.CurrentToken = Context.BufferedTokens.Pop();
157 private void ComputeCurrentTerminals() {
158 Context.CurrentTerminals.Clear();
159 TerminalList termsForCurrentChar;
160 if(!Data.TerminalsLookup.TryGetValue(SourceStream.PreviewChar, out termsForCurrentChar))
161 termsForCurrentChar = Data.FallbackTerminals;
164 || Context.CurrentParserState == null || Grammar.FlagIsSet(
LanguageFlags.DisableScannerParserLink)
165 || Context.Mode == ParseMode.VsLineScan) {
166 Context.CurrentTerminals.AddRange(termsForCurrentChar);
170 var parserState = Context.CurrentParserState;
171 foreach(var term
in termsForCurrentChar) {
174 if (parserState.ExpectedTerminals.Contains(term.OutputTerminal) || Grammar.NonGrammarTerminals.Contains(term))
175 Context.CurrentTerminals.Add(term);
180 private void MatchTerminals() {
181 Token priorToken = null;
182 foreach (Terminal term
in Context.CurrentTerminals) {
186 if (priorToken != null && priorToken.Terminal.Priority > term.Priority)
189 SourceStream.ResetPreviewPosition();
190 var token = term.TryMatch(Context, SourceStream);
191 if (token == null)
continue;
193 if (priorToken != null && !priorToken.IsError() && (token.Length < priorToken.Length))
195 Context.CurrentToken = token;
196 term.InvokeValidateToken(Context);
197 if (Context.CurrentToken != null)
198 priorToken = Context.CurrentToken;
204 #region VS Integration methods
209 Context.VsLineScanState.Value = state;
214 Terminal term = Data.MultilineTerminals[Context.VsLineScanState.TerminalIndex - 1];
215 Context.CurrentToken = term.TryMatch(Context,
SourceStream);
218 state = Context.VsLineScanState.Value;
219 if (Context.CurrentToken != null && Context.CurrentToken.Terminal ==
Grammar.
Eof)
221 return Context.CurrentToken;
224 SourceStream.SetText(text, offset,
true);
228 #region Error recovery
229 private bool Recover() {
230 SourceStream.PreviewPosition++;
231 var wsd = Data.Language.GrammarData.WhitespaceAndDelimiters;
234 SourceStream.MoveLocationToPreviewPosition();
237 SourceStream.PreviewPosition++;
251 SourceLocation _previewStartLocation;
256 _previewStartLocation = SourceStream.Location;
261 base.EndPreview(keepPreviewTokens);
262 if (!keepPreviewTokens) {
263 Context.SetSourceLocation(_previewStartLocation);
TokenCategory
Token category.
void MoveLocationToPreviewPosition()
Scanner base class. The Scanner's function is to transform a stream of characters into aggregates/wor...
override void NextToken()
Retrieves the next token.
override void EndPreview(bool keepPreviewTokens)
Ends the preview.
void VsSetSource(string text, int offset)
Token VsReadToken(ref int state)
static SourceLocation Empty
override void PrepareInput()
Prepares the input.
Tokens are produced by scanner and fed to parser, optionally passing through Token filters in between...
static string ErrInvalidChar
Looks up a localized string similar to Invalid character: '{0}'..
override void BeginPreview()
Begins the preview.