Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
FreeTextLiteral.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.Linq;
16 using System.Text;
17 
18 namespace Irony.Parsing {
19  // Sometimes language definition includes tokens that have no specific format, but are just "all text until some terminator character(s)";
20  // FreeTextTerminal allows easy implementation of such language element.
21 
22  [Flags]
23  public enum FreeTextOptions {
24  None = 0x0,
25  ConsumeTerminator = 0x01, //move source pointer beyond terminator (so token "consumes" it from input), but don't include it in token text
26  IncludeTerminator = 0x02, // include terminator into token text/value
27  AllowEof = 0x04, // treat EOF as legitimate terminator
28  }
29 
30  public class FreeTextLiteral : Terminal {
31  public StringSet Terminators = new StringSet();
32  public StringSet Firsts = new StringSet();
33  public StringDictionary Escapes = new StringDictionary();
35  private char[] _stopChars;
36 
37  public FreeTextLiteral(string name, params string[] terminators) : this(name, FreeTextOptions.None, terminators) { }
38  public FreeTextLiteral(string name, FreeTextOptions freeTextOptions, params string[] terminators) : base(name) {
39  FreeTextOptions = freeTextOptions;
40  Terminators.UnionWith(terminators);
41  base.SetFlag(TermFlags.IsLiteral);
42  }//constructor
43 
44  public override IList<string> GetFirsts() {
45  var result = new StringList();
46  result.AddRange(Firsts);
47  return result;
48  }
49  public override void Init(GrammarData grammarData) {
50  base.Init(grammarData);
51  var stopChars = new CharHashSet();
52  foreach (var key in Escapes.Keys)
53  stopChars.Add(key[0]);
54  foreach (var t in Terminators)
55  stopChars.Add(t[0]);
56  _stopChars = stopChars.ToArray();
57  }
58 
59  public override Token TryMatch(ParsingContext context, ISourceStream source) {
60  string tokenText = string.Empty;
61  while (true) {
62  //Find next position
63  var newPos = source.Text.IndexOfAny(_stopChars, source.PreviewPosition);
64  if(newPos == -1) {
65  if(IsSet(FreeTextOptions.AllowEof)) {
66  source.PreviewPosition = source.Text.Length;
67  return source.CreateToken(this.OutputTerminal);
68  } else
69  return null;
70  }
71  tokenText += source.Text.Substring(source.PreviewPosition, newPos - source.PreviewPosition);
72  source.PreviewPosition = newPos;
73  //if it is escape, add escaped text and continue search
74  if (CheckEscape(source, ref tokenText))
75  continue;
76  //check terminators
77  if (CheckTerminators(source, ref tokenText))
78  break; //from while (true)
79  }
80  return source.CreateToken(this.OutputTerminal, tokenText);
81  }
82 
83  private bool CheckEscape(ISourceStream source, ref string tokenText) {
84  foreach (var dictEntry in Escapes) {
85  if (source.MatchSymbol(dictEntry.Key, !Grammar.CaseSensitive)) {
86  source.PreviewPosition += dictEntry.Key.Length;
87  tokenText += dictEntry.Value;
88  return true;
89  }
90  }//foreach
91  return false;
92  }
93 
94  private bool CheckTerminators(ISourceStream source, ref string tokenText) {
95  foreach(var term in Terminators)
96  if(source.MatchSymbol(term, !Grammar.CaseSensitive)) {
97  if (IsSet(FreeTextOptions.IncludeTerminator))
98  tokenText += term;
99  if (IsSet(FreeTextOptions.ConsumeTerminator | FreeTextOptions.IncludeTerminator))
100  source.PreviewPosition += term.Length;
101  return true;
102  }
103  return false;
104  }
105 
106  private bool IsSet(FreeTextOptions option) {
107  return (this.FreeTextOptions & option) != 0;
108  }
109  }//class
110 
111 }//namespace
Interface for Terminals to access the source stream and produce tokens.
override void Init(GrammarData grammarData)
Flags
Enumeration of the new Assimp's flags.
readonly bool CaseSensitive
Gets case sensitivity of the grammar. Read-only, true by default. Can be set to false only through a ...
Definition: Grammar.cs:27
override Token TryMatch(ParsingContext context, ISourceStream source)
FreeTextLiteral(string name, params string[] terminators)
override IList< string > GetFirsts()
FreeTextLiteral(string name, FreeTextOptions freeTextOptions, params string[] terminators)
Tokens are produced by scanner and fed to parser, optionally passing through Token filters in between...
Definition: Token.cs:74
bool MatchSymbol(string symbol, bool ignoreCase)
Tries to match the symbol with the text at current preview position.
int Length
Gets the length.
Definition: Token.cs:131