Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Scanner.cs
Go to the documentation of this file.
1 #region License
2 
3 /* **********************************************************************************
4  * Copyright (c) Roman Ivantsov
5  * This source code is subject to terms and conditions of the MIT License
6  * for Irony. A copy of the license can be found in the License.txt file
7  * at the root of this distribution.
8  * By using this source code in any fashion, you are agreeing to be bound by the terms of the
9  * MIT License.
10  * You must not remove this notice from this software.
11  * **********************************************************************************/
12 #endregion
13 
14 using System.Collections.Generic;
15 
16 namespace Irony.Parsing
17 {
18  /// <summary>
19  /// Scanner base class. The Scanner's function is to transform a stream of characters into aggregates/words or lexemes,
20  /// like identifier, number, literal, etc.
21  /// </summary>
22  public abstract class Scanner
23  {
24  #region Constants and Fields
25 
26  private readonly TokenStack bufferedTokens = new TokenStack();
27 
28  private readonly TokenStack previewTokens = new TokenStack();
29 
30  private IEnumerator<Token> filteredTokens; // stream of tokens after filter
31 
32  private SourceLocation previewStartLocation;
33 
34  #endregion
35 
36  #region Constructors and Destructors
37 
38  /// <summary>
39  /// Initializes a new instance of the <see cref = "Scanner" /> class.
40  /// </summary>
41  public Scanner()
42  {
43  }
44 
45  #endregion
46 
47  #region Public Properties
48 
49  /// <summary>
50  /// Gets or sets the location.
51  /// </summary>
52  /// <value>
53  /// The location.
54  /// </value>
55  public abstract SourceLocation Location { get; set; }
56 
57  /// <summary>
58  /// Gets the parser.
59  /// </summary>
60  public Parser Parser { get; private set; }
61 
62  #endregion
63 
64  #region Properties
65 
66  /// <summary>
67  /// Gets the context.
68  /// </summary>
69  protected ParsingContext Context
70  {
71  get
72  {
73  return Parser.Context;
74  }
75  }
76 
77  /// <summary>
78  /// Gets or sets the grammar.
79  /// </summary>
80  /// <value>
81  /// The grammar.
82  /// </value>
83  protected Grammar Grammar { get; set; }
84 
85  #endregion
86 
87  #region Public Methods
88 
89  /// <summary>
90  /// Begins the preview.
91  /// </summary>
92  public virtual void BeginPreview()
93  {
94  Context.Status = ParserStatus.Previewing;
95  previewTokens.Clear();
96  previewStartLocation = Location;
97  }
98 
99  // Ends preview mode
100 
101  /// <summary>
102  /// Ends the preview.
103  /// </summary>
104  /// <param name="keepPreviewTokens">
105  /// if set to <c>true</c> [keep preview tokens].
106  /// </param>
107  public virtual void EndPreview(bool keepPreviewTokens)
108  {
109  if (keepPreviewTokens)
110  {
111  // insert previewed tokens into buffered list, so we don't recreate them again
112  while (previewTokens.Count > 0)
113  {
114  bufferedTokens.Push(previewTokens.Pop());
115  }
116  }
117  else
118  {
119  Context.SetSourceLocation(previewStartLocation);
120  }
121 
122  previewTokens.Clear();
123  Context.Status = ParserStatus.Parsing;
124  }
125 
126  /// <summary>
127  /// Gets the next token.
128  /// </summary>
129  /// <returns>
130  /// A Token
131  /// </returns>
132  public Token GetToken()
133  {
134  // get new token from pipeline
135  if (!filteredTokens.MoveNext())
136  {
137  return null;
138  }
139 
140  var token = filteredTokens.Current;
141  if (Context.Status == ParserStatus.Previewing)
142  {
143  previewTokens.Push(token);
144  }
145  else
146  {
147  Context.CurrentParseTree.Tokens.Add(token);
148  }
149 
150  return token;
151  }
152 
153  /// <summary>
154  /// Initializes this instance.
155  /// </summary>
156  /// <param name="parser">
157  /// The Parser.
158  /// </param>
159  public void Initialize(Parser parser)
160  {
161  Parser = parser;
162  Grammar = parser.Language.Grammar;
163 
164  PrepareInput();
165 
166  // create token streams
167  var tokenStream = GetUnfilteredTokens();
168 
169  // chain all token filters
170  Context.TokenFilters.Clear();
171  Grammar.CreateTokenFilters(Parser.Language, Context.TokenFilters);
172  foreach (var filter in Context.TokenFilters)
173  {
174  tokenStream = filter.BeginFiltering(Context, tokenStream);
175  }
176 
177  filteredTokens = tokenStream.GetEnumerator();
178  }
179 
180  /// <summary>
181  /// Resets this instance.
182  /// </summary>
183  public virtual void Reset()
184  {
185  }
186 
187  /// <summary>
188  /// Sets the source text for this scanner.
189  /// </summary>
190  /// <param name="sourceText">The source text.</param>
191  public abstract void SetSourceText(string sourceText, string sourceFileName);
192 
193  #endregion
194 
195  #region Methods
196 
197  /// <summary>
198  /// Gets the unfiltered tokens.
199  /// </summary>
200  /// <returns>
201  /// An enumeration on the token
202  /// </returns>
204  {
205  // This is iterator method, so it returns immediately when called directly
206  // returns unfiltered, "raw" token stream
207  // We don't do "while(!_source.EOF())... because on EOF() we need to continue and produce EOF token
208  while (true)
209  {
210  Context.PreviousToken = Context.CurrentToken;
211  Context.CurrentToken = null;
212 
213  if (bufferedTokens.Count > 0)
214  {
215  Context.CurrentToken = bufferedTokens.Pop();
216  }
217  else
218  {
219  NextToken();
220  }
221 
222  Context.OnTokenCreated();
223 
224  // Don't yield break, continue returning EOF
225  yield return Context.CurrentToken;
226  }
227  }
228 
229  /// <summary>
230  /// Retrieves the next token.
231  /// </summary>
232  protected abstract void NextToken();
233 
234  /// <summary>
235  /// Prepares the input.
236  /// </summary>
237  protected abstract void PrepareInput();
238 
239  #endregion
240  }
241 }
virtual void Reset()
Resets this instance.
Definition: Scanner.cs:183
Scanner()
Initializes a new instance of the Scanner class.
Definition: Scanner.cs:41
Token GetToken()
Gets the next token.
Definition: Scanner.cs:132
Scanner base class. The Scanner's function is to transform a stream of characters into aggregates/wor...
Definition: Scanner.cs:22
A Stack of tokens.
Definition: Token.cs:67
virtual void EndPreview(bool keepPreviewTokens)
Ends the preview.
Definition: Scanner.cs:107
IEnumerable< Token > GetUnfilteredTokens()
Gets the unfiltered tokens.
Definition: Scanner.cs:203
virtual void BeginPreview()
Begins the preview.
Definition: Scanner.cs:92
Tokens are produced by scanner and fed to parser, optionally passing through Token filters in between...
Definition: Token.cs:74
void Initialize(Parser parser)
Initializes this instance.
Definition: Scanner.cs:159