Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Tokenizer.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 
7 using GoldParser;
8 
9 using Irony.Parsing;
10 using SiliconStudio.Shaders.Properties;
11 
12 namespace SiliconStudio.Shaders.Grammar
13 {
14  public class Tokenizer
15  {
16  internal GoldParser.Parser GoldParser;
17  private static GoldParser.Grammar grammar;
18  private ShaderLanguageData languageData;
19  private string source;
20 
21  int previousLine = 0;
22  int newLine = 0;
23  private string sourceFileName = null;
24 
25  static Tokenizer()
26  {
27  var grammarStream = new MemoryStream(Resources.Tokenizer); // new FileStream("Preprocessor.cgt", FileMode.Open, FileAccess.Read);
28  grammar = new GoldParser.Grammar(new BinaryReader(grammarStream));
29  grammarStream.Close();
30  }
31 
32  public Tokenizer(ShaderLanguageData languageData)
33  {
34  GoldParser = new GoldParser.Parser(grammar);
35  this.languageData = languageData;
36  }
37 
38  public Irony.Parsing.SourceLocation Location
39  {
40  get
41  {
42  return new Irony.Parsing.SourceLocation(GoldParser.CharPosition, (GoldParser.LineNumber - previousLine) + newLine, GoldParser.LinePosition, sourceFileName);
43  }
44  set
45  {
46  int tempNewLine = (value.Line - newLine) + previousLine;
47  // Console.WriteLine("New source line location: {0} {1} {2} / Previous {3} {4} {5} / Preprocessor Line {6} {7} => NewLine {8}", value.Position, value.Line, value.Column, GoldParser.CharPosition, GoldParser.LineNumber, GoldParser.LinePosition, previousLine, newLine, tempNewLine);
48  GoldParser.CharPosition = value.Position;
49  GoldParser.LineNumber = tempNewLine;
50  }
51  }
52 
53  public void SetSourceText(string sourceText, string sourceFileName)
54  {
55  source = sourceText;
56  GoldParser.SetSourceCode(sourceText);
57  previousLine = 0;
58  newLine = 0;
59  this.sourceFileName = sourceFileName;
60  }
61 
63  {
64  var location = Location;
65  var symbol = GoldParser.ReadToken();
66  Token token = null;
67 
68  var tokenType = (TokenType)symbol.Index;
69 
70  // Else process the symbol as it should
71  switch (symbol.SymbolType)
72  {
73  case SymbolType.WhiteSpace:
74  token = new Token(languageData.FindTerminalByType(tokenType), location, GoldParser.TokenLength, source, null);
75  break;
76 
77  case SymbolType.CommentLine:
78  case SymbolType.CommentStart:
79  int length = GoldParser.CommentTextLength(location.Position) - location.Position;
80  token = new Token(languageData.FindTerminalByType(tokenType), location, length, source, null);
81  break;
82  case SymbolType.Error:
83  token = new Token(languageData.Grammar.SyntaxError, location, GoldParser.TokenLength, source, "Unexpected token");
84  break;
85  case SymbolType.End:
86  token = new Token(languageData.Grammar.Eof, location, string.Empty, languageData.Grammar.Eof.Name);
87  break;
88  default:
89 
90  // Skip preprocessor line
91  // Update line number according to
92  if (symbol.Index == (int)TokenType.Preprocessor)
93  {
94  int tempPreviousLine = GoldParser.LineNumber;
95  bool isEndOfLine = false;
96 
97  bool preprocessorDecoded = false;
98 
99  while (!isEndOfLine)
100  {
101  symbol = GoldParser.ReadToken();
102  tokenType = (TokenType)symbol.Index;
103 
104  switch ((TokenType)symbol.Index)
105  {
106  case TokenType.Eof:
107  case TokenType.NewLine:
108  isEndOfLine = true;
109  break;
110  case TokenType.Identifier:
111  if (!preprocessorDecoded)
112  preprocessorDecoded = GoldParser.TokenText != "line";
113 
114  break;
115  case TokenType.StringLiteral:
116  if (preprocessorDecoded)
117  sourceFileName = GoldParser.TokenText.Trim('"').Replace(@"\\", @"\");
118  break;
119  case TokenType.WS:
120  case TokenType.Whitespace:
121  break;
122  case TokenType.StartWithNoZeroDecimalIntegerLiteral:
123  if (!preprocessorDecoded)
124  {
125  previousLine = tempPreviousLine;
126  newLine = int.Parse(GoldParser.TokenText) - 1;
127  preprocessorDecoded = true;
128  }
129  break;
130  default:
131  preprocessorDecoded = true;
132  break;
133  }
134  }
135 
136  location = Location;
137  }
138 
139 
140  Terminal terminal = null;
141  if (tokenType == TokenType.Identifier)
142  terminal = languageData.FindTerminalByName(GoldParser.TokenText);
143 
144  if (terminal == null)
145  terminal = languageData.FindTerminalByType((TokenType)symbol.Index);
146 
147  if (terminal == null)
148  {
149  token = new Token(languageData.Grammar.SyntaxError, location, GoldParser.TokenText, string.Format("Unable to find terminal for token text [{0}]", GoldParser.TokenText));
150  }
151  else
152  {
153  if (terminal is DynamicKeyTerm)
154  {
155  ((DynamicKeyTerm)terminal).Match(this, out token);
156  }
157  else
158  {
159  token = new Token(terminal, location, GoldParser.TokenLength, source, null);
160  }
161  }
162  break;
163  }
164 
165  return token;
166  }
167  }
168 }
Tokenizer(ShaderLanguageData languageData)
Definition: Tokenizer.cs:32
void SetSourceText(string sourceText, string sourceFileName)
Definition: Tokenizer.cs:53
switch(inFormat)
Tokens are produced by scanner and fed to parser, optionally passing through Token filters in between...
Definition: Token.cs:74