Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
ParsingContext.cs
Go to the documentation of this file.
1 #region License
2 /* **********************************************************************************
3  * Copyright (c) Roman Ivantsov
4  * This source code is subject to terms and conditions of the MIT License
5  * for Irony. A copy of the license can be found in the License.txt file
6  * at the root of this distribution.
7  * By using this source code in any fashion, you are agreeing to be bound by the terms of the
8  * MIT License.
9  * You must not remove this notice from this software.
10  * **********************************************************************************/
11 #endregion
12 
13 using System;
14 using System.Collections.Generic;
15 using System.Text;
16 using System.Runtime.InteropServices;
17 using System.Diagnostics;
18 using System.Globalization;
19 
20 namespace Irony.Parsing {
21 
22  [Flags]
23  public enum ParseOptions {
24  GrammarDebugging = 0x01,
25  TraceParser = 0x02,
26  AnalyzeCode = 0x10, //run code analysis; effective only in Module mode
27  }
28 
29  public enum ParseMode {
30  File, //default, continuous input file
31  VsLineScan, // line-by-line scanning in VS integration for syntax highlighting
32  CommandLine, //line-by-line from console
33  }
34 
35  public enum ParserStatus {
36  Init, //initial state
37  Parsing,
38  Previewing, //previewing tokens
39  Recovering, //recovering from error
40  Accepted,
42  Error,
43  }
44 
45  // The purpose of this class is to provide a container for information shared
46  // between parser, scanner and token filters.
47  public class ParsingContext {
48  public readonly Parser Parser;
49  public readonly LanguageData Language;
50 
51  //Parser settings
53  public ParseMode Mode = ParseMode.File;
54  public int MaxErrors = 20; //maximum error count to report
55  public CultureInfo Culture; //defaults to Grammar.DefaultCulture, might be changed by app code
56 
57  #region properties and fields
58  //Parser fields
59  public ParserState CurrentParserState { get; internal set; }
60  public ParseTreeNode CurrentParserInput { get; internal set; }
61  public readonly ParserStack ParserStack = new ParserStack();
62  internal readonly ParserStack ParserInputStack = new ParserStack();
63 
64  public ParseTree CurrentParseTree { get; internal set; }
65  public readonly TokenStack OpenBraces = new TokenStack();
67  //public ISourceStream Source { get { return SourceStream; } }
68  //list for terminals - for current parser state and current input char
69  public TerminalList CurrentTerminals = new TerminalList();
70  public Token CurrentToken; //The token just scanned by Scanner
72  public SourceLocation PreviousLineStart; //Location of last line start
73 
74  //Internal fields
75  //internal SourceStream SourceStream;
76  internal TokenFilterList TokenFilters = new TokenFilterList();
77  internal ParsingEventArgs SharedParsingEventArgs;
78 
79  public VsScannerStateMap VsLineScanState; //State variable used in line scanning mode for VS integration
80 
81  public ParserStatus Status {get; internal set;}
82  public bool HasErrors; //error flag, once set remains set
83 
84  //values dictionary to use by custom language implementations to save some temporary values in parse process
85  public readonly Dictionary<string, object> Values = new Dictionary<string, object>();
86 
87  public int TabWidth
88  {
89  get { return _tabWidth; }
90  set
91  {
92  _tabWidth = value;
93  }
94  }
95  int _tabWidth = 8;
96 
97  #endregion
98 
99 
100  #region constructors
101  public ParsingContext(Parser parser) {
102  this.Parser = parser;
103  Language = Parser.Language;
104  Culture = Language.Grammar.DefaultCulture;
105  //This might be a problem for multi-threading - if we have several contexts on parallel threads with different culture.
106  //Resources.Culture is static property (this is not Irony's fault, this is auto-generated file).
107  Resources.Culture = Culture;
108  //We assume that if Irony is compiled in Debug mode, then developer is debugging his grammar/language implementation
109 #if DEBUG
110  Options |= ParseOptions.GrammarDebugging;
111 #endif
112  SharedParsingEventArgs = new ParsingEventArgs(this);
113  }
114  #endregion
115 
116 
117  #region Events: TokenCreated
118  public event EventHandler<ParsingEventArgs> TokenCreated;
119 
120  internal void OnTokenCreated() {
121  if (TokenCreated != null)
122  TokenCreated(this, SharedParsingEventArgs);
123  }
124  #endregion
125 
126  #region Options helper methods
127  public bool OptionIsSet(ParseOptions option) {
128  return (Options & option) != 0;
129  }
130  public void SetOption(ParseOptions option, bool value) {
131  if (value)
132  Options |= option;
133  else
134  Options &= ~option;
135  }
136  #endregion
137 
138  #region Error handling and tracing
139  public void AddParserError(string message, params object[] args) {
140  var location = CurrentParserInput == null? Parser.Scanner.Location : CurrentParserInput.Span.Location;
141  HasErrors = true;
142  AddParserMessage(ParserErrorLevel.Error, location, message, args);
143  }
144  public void AddParserMessage(ParserErrorLevel level, SourceLocation location, string message, params object[] args) {
145  if (CurrentParseTree == null) return;
146  if (CurrentParseTree.ParserMessages.Count >= MaxErrors) return;
147  if (args != null && args.Length > 0)
148  message = string.Format(message, args);
149  CurrentParseTree.ParserMessages.Add(new ParserMessage(level, location, message, CurrentParserState));
150  if (OptionIsSet(ParseOptions.TraceParser))
151  ParserTrace.Add( new ParserTraceEntry(CurrentParserState, ParserStack.Top, CurrentParserInput, message, true));
152  }
153 
154  public void AddTrace(string message, params object[] args) {
155  if (!OptionIsSet(ParseOptions.TraceParser)) return;
156  if (args != null && args.Length > 0)
157  message = string.Format(message, args);
158  ParserTrace.Add(new ParserTraceEntry(CurrentParserState, ParserStack.Top, CurrentParserInput, message, false));
159  }
160 
161  #endregion
162 
163  internal void Reset() {
164  CurrentParserState = Parser.InitialState;
165  CurrentParserInput = null;
166  ParserStack.Clear();
167  HasErrors = false;
168  ParserStack.Push(new ParseTreeNode(CurrentParserState));
169  ParserInputStack.Clear();
170  CurrentParseTree = null;
171  OpenBraces.Clear();
172  ParserTrace.Clear();
173  CurrentTerminals.Clear();
174  CurrentToken = null;
175  PreviousToken = null;
176  PreviousLineStart = new SourceLocation(0, -1, 0);
177  Values.Clear();
178  foreach (var filter in TokenFilters)
179  filter.Reset();
180  }
181 
182  public void SetSourceLocation(SourceLocation location) {
183  foreach (var filter in TokenFilters)
184  filter.OnSetSourceLocation(location);
185  Parser.Scanner.Location = location;
186  }
187 
188  #region Expected term set computations
190  if (CurrentParserState == null)
191  return new StringSet();
192  //See note about multi-threading issues in ComputeReportedExpectedSet comments.
193  if (CurrentParserState.ReportedExpectedSet == null)
194  CurrentParserState.ReportedExpectedSet = CoreParser.ComputeGroupedExpectedSetForState(Language.Grammar, CurrentParserState);
195  //Filter out closing braces which are not expected based on previous input.
196  // While the closing parenthesis ")" might be expected term in a state in general,
197  // if there was no opening parenthesis in preceding input then we would not
198  // expect a closing one.
199  var expectedSet = FilterBracesInExpectedSet(CurrentParserState.ReportedExpectedSet);
200  return expectedSet;
201  }
202 
203  private StringSet FilterBracesInExpectedSet(StringSet stateExpectedSet) {
204  var result = new StringSet();
205  result.UnionWith(stateExpectedSet);
206  //Find what brace we expect
207  var nextClosingBrace = string.Empty;
208  if (OpenBraces.Count > 0) {
209  var lastOpenBraceTerm = OpenBraces.Peek().KeyTerm;
210  var nextClosingBraceTerm = lastOpenBraceTerm.IsPairFor as KeyTerm;
211  if (nextClosingBraceTerm != null)
212  nextClosingBrace = nextClosingBraceTerm.Text;
213  }
214  //Now check all closing braces in result set, and leave only nextClosingBrace
215  foreach(var closingBrace in Language.GrammarData.ClosingBraces) {
216  if (result.Contains(closingBrace) && closingBrace != nextClosingBrace)
217  result.Remove(closingBrace);
218 
219  }
220  return result;
221  }
222 
223  #endregion
224 
225 
226  }//class
227 
228  // A struct used for packing/unpacking ScannerState int value; used for VS integration.
229  // When Terminal produces incomplete token, it sets
230  // this state to non-zero value; this value identifies this terminal as the one who will continue scanning when
231  // it resumes, and the terminal's internal state when there may be several types of multi-line tokens for one terminal.
232  // For ex., there maybe several types of string literal like in Python.
233  [StructLayout(LayoutKind.Explicit)]
234  public struct VsScannerStateMap {
235  [FieldOffset(0)]
236  public int Value;
237  [FieldOffset(0)]
238  public byte TerminalIndex; //1-based index of active multiline term in MultilineTerminals
239  [FieldOffset(1)]
240  public byte TokenSubType; //terminal subtype (used in StringLiteral to identify string kind)
241  [FieldOffset(2)]
242  public short TerminalFlags; //Terminal flags
243  }//struct
244 
245 
246 }
readonly ParserStack ParserStack
SourceLocation PreviousLineStart
Definition: ParserTrace.cs:19
A Stack of tokens.
Definition: Token.cs:67
Flags
Enumeration of the new Assimp's flags.
bool OptionIsSet(ParseOptions option)
void SetOption(ParseOptions option, bool value)
void AddParserMessage(ParserErrorLevel level, SourceLocation location, string message, params object[] args)
System.IO.File File
void SetSourceLocation(SourceLocation location)
Describes a language.
Definition: LanguageData.cs:23
VsScannerStateMap VsLineScanState
EventHandler< ParsingEventArgs > TokenCreated
Tokens are produced by scanner and fed to parser, optionally passing through Token filters in between...
Definition: Token.cs:74
void AddParserError(string message, params object[] args)
readonly LanguageData Language
void AddTrace(string message, params object[] args)