aboutsummaryrefslogtreecommitdiffstatsci
path: root/CrowIDE/src/SourceEditor/StyleParser.cs
blob: a4273ede22b138e52be11b8d818682f0822f4242 (plain)
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
using System;
using Crow;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Linq;

namespace Crow.Coding
{
	public class StyleParser : BufferParser
	{
		enum States { init, classNames, members, value, endOfStatement }

		public StyleParser (CodeBuffer _buffer) : base(_buffer)
		{
		}

		#region Character ValidityCheck
		static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
		static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}");															
		static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}");
		static Regex rxDecimal = new Regex(@"[0-9]+");
		static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+");

		public bool nextCharIsValidCharStartName
		{
			get { return rxNameStartChar.IsMatch(new string(new char[]{Peek()})); }
		}
		public bool nextCharIsValidCharName
		{
			get { return rxNameChar.IsMatch(new string(new char[]{Peek()})); }
		}
		#endregion

		States curState = States.classNames;

		public override void ParseCurrentLine ()
		{
			Debug.WriteLine (string.Format("parsing line:{0}", currentLine));
			CodeLine cl = buffer [currentLine];
			cl.Tokens = new List<Token> ();

			//retrieve current parser state from previous line
			if (currentLine > 0)
				curState = (States)buffer[currentLine - 1].EndingState;
			else
				curState = States.init;

			States previousEndingState = (States)cl.EndingState;

			while (! eol) {
				SkipWhiteSpaces ();

				if (eol)
					break;

				if (Peek () == '\n') {
					if (currentTok != TokenType.Unknown)
						throw new ParserException (currentLine, currentColumn, "Unexpected end of line");
					Read ();
					eol = true;
					continue;
				}

				switch (Peek()) {
				case '/':
					readToCurrTok (true);
					switch (Peek ()) {
					case '/':
						currentTok += ReadLine ();
						saveAndResetCurrentTok (TokenType.LineComment);
						break;
					default:
						currentTok += ReadLine ();
						saveAndResetCurrentTok (TokenType.Unknown);
						break;
					}
					break;
				case ',':
					if (curState != States.init || curState != States.classNames )
						throw new ParserException (currentLine, currentColumn, "Unexpected char ','");
					readAndResetCurrentTok (TokenType.UnaryOp, true);
					curState = States.classNames;
					break;
				case '{':
					if (!(curState == States.init || curState == States.classNames))
						throw new ParserException (currentLine, currentColumn, "Unexpected char '{'");
					readAndResetCurrentTok (TokenType.OpenBlock, true);
					curState = States.members;
					break;
				case '}':
					if (curState != States.members)
						throw new ParserException (currentLine, currentColumn, "Unexpected char '}'");
					readAndResetCurrentTok (TokenType.CloseBlock, true);
					curState = States.classNames;
					break;
				case '=':
					if (curState == States.classNames)
						throw new ParserException (currentLine, currentColumn, "Unexpected char '='");
					readAndResetCurrentTok (TokenType.Affectation, true);
					curState = States.value;
					break;
				case '"':
					if (curState != States.value)
						throw new ParserException (currentLine, currentColumn, "Unexpected char '\"'");					
					readAndResetCurrentTok (TokenType.StringLitteralOpening, true);

					while (!eol) {
						currentTok += ReadLineUntil ("\"");
						if (currentTok.Content [currentTok.Content.Length - 1] == '\\')
							readToCurrTok ();
						else
							break;
					}
					if (eol)
						throw new ParserException (currentLine, currentColumn, "Unexpected end of line");
					saveAndResetCurrentTok (TokenType.StringLitteral);

					readAndResetCurrentTok (TokenType.StringLitteralClosing, true);
					curState = States.endOfStatement;
					break;
				case ';':
					if (curState != States.endOfStatement)
						throw new ParserException (currentLine, currentColumn, "Unexpected end of statement");					
					readAndResetCurrentTok (TokenType.StatementEnding, true);
					curState = States.members;
					break;
				default:
					if (currentTok.Type != TokenType.Unknown)
						throw new ParserException (currentLine, currentColumn, "error curtok not null");
					if (curState == States.value)
						throw new ParserException (currentLine, currentColumn, "expecting value enclosed in '\"'");
					if (curState == States.endOfStatement)
						throw new ParserException (currentLine, currentColumn, "expecting end of statement");					
					
					if (nextCharIsValidCharStartName) {						
						readToCurrTok (true);
						while (nextCharIsValidCharName)
							readToCurrTok ();
					}
					saveAndResetCurrentTok (TokenType.Identifier);
					break;
				}
			}

			if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1)
				buffer [currentLine + 1].Tokens = null;

			cl.EndingState = (int)curState;
		}
		public override void SyntaxAnalysis ()
		{
			RootNode = new Node () { Name = "RootNode", Type="Root" };
		}
	}
}