1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
|
using System;
using System.IO;
using Crow;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace Crow.Coding
{
/// <summary>
/// base class for tokenizing sources
/// </summary>
public abstract class BufferParser
{
/// <summary>
/// Default tokens, this enum may be overriden in derived parser with the new keyword,
/// see XMLParser for example.
/// </summary>
public enum TokenType {
Unknown = 0,
WhiteSpace = 1,
NewLine = 2,
LineComment = 3,
BlockCommentStart = 4,
BlockComment = 5,
BlockCommentEnd = 6,
Preprocessor = 7,
Identifier = 8,
Keyword = 9,
OpenBlock = 10,
CloseBlock = 11,
StatementEnding = 12,
OperatorOrPunctuation = 13,
IntegerLitteral = 14,
RealLitteral = 15,
StringLitteralOpening = 16,
StringLitteralClosing = 17,
StringLitteral = 18,
CharLitteralOpening = 19,
CharLitteralClosing = 20,
CharLitteral = 21,
BoolLitteral = 22,
NullLitteral = 23,
Type = 24,
}
#region CTOR
public BufferParser (CodeBuffer _buffer)
{
buffer = _buffer;
buffer.LineUpadateEvent += Buffer_LineUpadateEvent;
//buffer.LineAdditionEvent += Buffer_LineAdditionEvent;;
buffer.LineRemoveEvent += Buffer_LineRemoveEvent;
buffer.BufferCleared += Buffer_BufferCleared;
}
#endregion
#region Buffer events handlers
void Buffer_BufferCleared (object sender, EventArgs e)
{
}
void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e)
{
}
void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e)
{
reparseSource ();
}
void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e)
{
for (int i = 0; i < e.LineCount; i++)
TryParseBufferLine (e.LineStart + i);
reparseSource ();
}
#endregion
internal int currentLine = 0;
internal int currentColumn = 0;
int syntTreeDepth = 0;
public int SyntacticTreeDepth {
get { return syntTreeDepth;}
set {
syntTreeDepth = value;
if (syntTreeDepth > SyntacticTreeMaxDepth)
SyntacticTreeMaxDepth = syntTreeDepth;
}
}
public int SyntacticTreeMaxDepth = 0;
protected CodeBuffer buffer;
protected Token currentTok;
protected bool eol = true;
protected Point CurrentPosition {
get { return new Point (currentLine, currentColumn); }
set {
currentLine = value.Y;
currentColumn = value.X;
}
}
public Node RootNode;
public abstract void ParseCurrentLine();
public abstract void SyntaxAnalysis ();
public void reparseSource () {
for (int i = 0; i < buffer.LineCount; i++) {
if (!buffer[i].IsParsed)
TryParseBufferLine (i);
}
try {
SyntaxAnalysis ();
} catch (Exception ex) {
Debug.WriteLine ("Syntax Error: " + ex.ToString ());
if (ex is ParserException)
SetLineInError (ex as ParserException);
}
}
public void TryParseBufferLine(int lPtr) {
buffer [lPtr].exception = null;
currentLine = lPtr;
currentColumn = 0;
eol = false;
try {
ParseCurrentLine ();
} catch (Exception ex) {
Debug.WriteLine (ex.ToString ());
if (ex is ParserException)
SetLineInError (ex as ParserException);
}
}
public virtual void SetLineInError(ParserException ex) {
currentTok = default(Token);
if (ex.Line >= buffer.LineCount)
ex.Line = buffer.LineCount - 1;
if (buffer [ex.Line].IsFolded)
buffer.ToogleFolding (ex.Line);
buffer [ex.Line].SetLineInError (ex);
}
public virtual string LineBrkRegex {
get { return @"\r\n|\r|\n|\\\\n"; }
}
void updateFolding () {
// Stack<TokenList> foldings = new Stack<TokenList>();
// bool inStartTag = false;
//
// for (int i = 0; i < parser.Tokens.Count; i++) {
// TokenList tl = parser.Tokens [i];
// tl.foldingTo = null;
// int fstTK = tl.FirstNonBlankTokenIndex;
// if (fstTK > 0 && fstTK < tl.Count - 1) {
// if (tl [fstTK + 1] != XMLParser.TokenType.ElementName)
// continue;
// if (tl [fstTK] == XMLParser.TokenType.ElementStart) {
// //search closing tag
// int tkPtr = fstTK+2;
// while (tkPtr < tl.Count) {
// if (tl [tkPtr] == XMLParser.TokenType.ElementClosing)
//
// tkPtr++;
// }
// if (tl.EndingState == (int)XMLParser.States.Content)
// foldings.Push (tl);
// else if (tl.EndingState == (int)XMLParser.States.StartTag)
// inStartTag = true;
// continue;
// }
// if (tl [fstTK] == XMLParser.TokenType.ElementEnd) {
// TokenList tls = foldings.Pop ();
// int fstTKs = tls.FirstNonBlankTokenIndex;
// if (tls [fstTK + 1].Content == tl [fstTK + 1].Content) {
// tl.foldingTo = tls;
// continue;
// }
// parser.CurrentPosition = tls [fstTK + 1].Start;
// parser.SetLineInError(new ParserException(parser, "closing tag not corresponding"));
// }
//
// }
// }
}
#region low level parsing
protected void addCharToCurTok(char c, Point position){
currentTok.Start = position;
currentTok += c;
}
/// <summary>
/// Read one char from current position in buffer and store it into the current token
/// </summary>
/// <param name="startOfTok">if true, set the Start position of the current token to the current position</param>
protected void readToCurrTok(bool startOfTok = false){
if (startOfTok)
currentTok.Start = CurrentPosition;
currentTok += Read();
}
/// <summary>
/// read n char from the buffer and store it into the current token
/// </summary>
protected void readToCurrTok(int length) {
for (int i = 0; i < length; i++)
currentTok += Read ();
}
/// <summary>
/// Save current token into current TokensLine and raz current token
/// </summary>
protected void saveAndResetCurrentTok() {
currentTok.End = CurrentPosition;
buffer[currentLine].Tokens.Add (currentTok);
currentTok = default(Token);
}
/// <summary>
/// read one char and add current token to current TokensLine, current token is reset
/// </summary>
/// <param name="type">Type of the token</param>
/// <param name="startToc">set start of token to current position</param>
protected void readAndResetCurrentTok(System.Enum type, bool startToc = false) {
readToCurrTok ();
saveAndResetCurrentTok (type);
}
/// <summary>
/// Save current tok
/// </summary>
/// <param name="type">set the type of the tok</param>
protected void saveAndResetCurrentTok(System.Enum type) {
currentTok.Type = (TokenType)type;
saveAndResetCurrentTok ();
}
protected void setPreviousTokOfTypeTo (TokenType inType, TokenType newType) {
for (int i = currentLine; i >= 0; i--) {
int j = buffer [i].Tokens.Count - 1;
while (j >= 0) {
if (buffer [i].Tokens [j].Type == inType) {
Token t = buffer [i].Tokens [j];
t.Type = newType;
buffer [i].Tokens [j] = t;
return;
}
j--;
}
}
}
/// <summary>
/// Peek next char, emit '\n' if current column > buffer's line length
/// Throw error if eof is true
/// </summary>
protected virtual char Peek() {
if (eol)
throw new ParserException (currentLine, currentColumn, "Unexpected End of line");
return currentColumn < buffer [currentLine].Length ?
buffer [currentLine] [currentColumn] : '\n';
}
/// <summary>
/// Peek n char from buffer or less if remaining char in buffer's line is less than requested
/// if end of line is reached, no '\n' will be emitted, instead, empty string is returned. '\n' should be checked only
/// with single char Peek().
/// Throw error is eof is true
/// </summary>
/// <param name="length">Length.</param>
protected virtual string Peek(int length) {
if (eol)
return "";//throw new ParserException (currentLine, currentColumn, "Unexpected End of Line");
int lg = Math.Min(length, Math.Max (buffer [currentLine].Length - currentColumn, buffer [currentLine].Length - currentColumn - length));
if (lg == 0)
return "";
return buffer [currentLine].Content.Substring (currentColumn, lg);
}
/// <summary>
/// read one char from buffer at current position, if '\n' is read, current line is incremented
/// and column is reset to 0
/// </summary>
protected virtual char Read() {
char c = Peek ();
if (c == '\n')
eol = true;
currentColumn++;
return c;
}
protected virtual string Read(int charCount){
string tmp = "";
for (int i = 0; i < charCount; i++) {
if (eol)
break;
tmp += Read ();
}
return tmp;
}
/// <summary>
/// read until end of line is reached
/// </summary>
/// <returns>string read</returns>
protected virtual string ReadLine () {
StringBuilder tmp = new StringBuilder();
char c = Read ();
while (!eol) {
tmp.Append (c);
c = Read ();
}
return tmp.ToString();
}
/// <summary>
/// read until end expression is reached or end of line.
/// </summary>
/// <returns>string read minus the ending expression that has to be read after</returns>
/// <param name="endExp">Expression to search for</param>
protected virtual string ReadLineUntil (string endExp){
string tmp = "";
while (!eol) {
if (buffer [currentLine].Length - currentColumn - endExp.Length < 0) {
tmp += ReadLine();
break;
}
if (string.Equals (Peek (endExp.Length), endExp))
return tmp;
tmp += Read();
}
return tmp;
}
/// <summary>
/// skip white spaces, but not line break. Save spaces in a WhiteSpace token.
/// </summary>
protected void SkipWhiteSpaces () {
if (currentTok.Type != TokenType.Unknown)
throw new ParserException (currentLine, currentColumn, "current token should be reset to unknown (0) before skiping white spaces");
while (!eol) {
if (!char.IsWhiteSpace (Peek ())||Peek()=='\n')
break;
readToCurrTok (currentTok.Type == TokenType.Unknown);
currentTok.Type = TokenType.WhiteSpace;
}
if (currentTok.Type != TokenType.Unknown)
saveAndResetCurrentTok ();
}
#endregion
protected Node addChildNode (Node curNode, CodeLine cl, int tokPtr, string type = "") {
Node n = new Node () { Name = cl.Tokens [tokPtr].Content, StartLine = cl, Type = type };
curNode.AddChild (n);
if (cl.SyntacticNode == null)
cl.SyntacticNode = n;
SyntacticTreeDepth++;
return n;
}
protected void closeNodeAndGoUp (ref Node n, CodeLine cl, string type = ""){
while (n != null) {
if (n.Type == type) {
n.EndLine = cl;
n = n.Parent;
SyntacticTreeDepth--;
break;
}
n = n.Parent;
SyntacticTreeDepth--;
}
}
protected void closeNodeAndGoUp (ref Node n, CodeLine cl){
SyntacticTreeDepth--;
n.EndLine = cl;
n = n.Parent;
}
protected void initSyntaxAnalysis () {
RootNode = new Node () { Name = "RootNode", Type="Root" };
SyntacticTreeDepth = SyntacticTreeMaxDepth = 0;
}
protected void throwParserException(string msg){
throw new ParserException (currentLine, currentColumn, msg);
}
}
}
|