Wrap always_inline and noinline attributes in compiler checks and use MSVC equivalent.
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / ConditionTokenizer.cs
1 //
2 // ConditionTokenizer.cs
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 //   Jaroslaw Kowalski <jaak@jkowalski.net>
7 // 
8 // (C) 2006 Marek Sieradzki
9 // (C) 2004-2006 Jaroslaw Kowalski
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 #if NET_2_0
31
32 using System;
33 using System.Collections;
34 using System.Collections.Generic;
35 using System.Collections.Specialized;
36 using System.Text;
37
38 namespace Microsoft.Build.BuildEngine {
39
40         internal sealed class ConditionTokenizer {
41         
42                 string  inputString = null;
43                 int     position = 0;
44                 int     tokenPosition = 0;
45                 
46                 Token   token;
47                 Token   putback = null;
48                 
49 //              bool    ignoreWhiteSpace = true;
50                 
51                 static TokenType[] charIndexToTokenType = new TokenType[128];
52                 static Dictionary <string, TokenType> keywords = new Dictionary <string, TokenType> (StringComparer.OrdinalIgnoreCase);
53
54                 static ConditionTokenizer ()
55                 {
56                         for (int i = 0; i < 128; i++)
57                                 charIndexToTokenType [i] = TokenType.Invalid;
58                         
59                         foreach (CharToTokenType cht in charToTokenType)
60                                 charIndexToTokenType [(int) cht.ch] = cht.tokenType;
61                         
62                         keywords.Add ("and", TokenType.And);
63                         keywords.Add ("or", TokenType.Or);
64                 }
65                 
66                 public ConditionTokenizer ()
67                 {
68 //                      this.ignoreWhiteSpace = true;
69                 }
70                 
71                 public void Tokenize (string s)
72                 {
73                         if (s == null)
74                                 throw new ArgumentNullException ("s");
75                 
76                         this.inputString = s;
77                         this.position = 0;
78                         this.token = new Token (null, TokenType.BOF, 0);
79
80                         GetNextToken ();
81                 }
82                 
83                 void SkipWhiteSpace ()
84                 {
85                         int ch;
86                         
87                         while ((ch = PeekChar ()) != -1) {
88                                 if (!Char.IsWhiteSpace ((char)ch))
89                                         break;
90                                 ReadChar ();
91                         }
92                 }
93                 
94                 int PeekChar ()
95                 {
96                         if (position < inputString.Length)
97                                 return (int) inputString [position];
98                         else
99                                 return -1;
100                 }
101                 
102                 int ReadChar ()
103                 {
104                         if (position < inputString.Length)
105                                 return (int) inputString [position++];
106                         else
107                                 return -1;
108                 }
109                 
110                 public void Expect (TokenType type)
111                 {
112                         if (token.Type != type)
113                                 throw new ExpressionParseException ("Expected token type of type: " + type + ", got " + token.Type +
114                                         " (" + token.Value + ") .");
115                         
116                         GetNextToken ();
117                 }
118                 
119                 public bool IsEOF ()
120                 {
121                         return token.Type == TokenType.EOF;
122                 }
123                 
124                 public bool IsNumber ()
125                 {
126                         return token.Type == TokenType.Number;
127                 }
128                 
129                 public bool IsToken (TokenType type)
130                 {
131                         return token.Type == type;
132                 }
133                 
134                 public bool IsPunctation ()
135                 {
136                         return (token.Type >= TokenType.FirstPunct && token.Type < TokenType.LastPunct);
137                 }
138                 
139                 // FIXME test this
140                 public void Putback (Token token)
141                 {
142                         putback = token;
143                 }
144                 
145                 public void GetNextToken ()
146                 {
147                         if (putback != null) {
148                                 token = putback;
149                                 putback = null;
150                                 return;
151                         }
152                 
153                         if (token.Type == TokenType.EOF)
154                                 throw new ExpressionParseException (String.Format (
155                                                         "Error while parsing condition \"{0}\", ended abruptly.",
156                                                         inputString));
157                         
158                         SkipWhiteSpace ();
159                         
160                         tokenPosition = position;
161                         
162 //                      int i = PeekChar ();
163                         int i = ReadChar ();
164                         
165                         if (i == -1) {
166                                 token = new Token (null, TokenType.EOF, tokenPosition);
167                                 return;
168                         }
169                         
170                         char ch = (char) i;
171
172                         
173                         // FIXME: looks like a hack: if '-' is here '->' won't be tokenized
174                         // maybe we should treat item reference as a token
175                         if (ch == '-' && PeekChar () == '>') {
176                                 ReadChar ();
177                                 token = new Token ("->", TokenType.Transform, tokenPosition);
178                         } else if (Char.IsDigit (ch) || ch == '-') {
179                                 StringBuilder sb = new StringBuilder ();
180                                 
181                                 sb.Append (ch);
182                                 
183                                 while ((i = PeekChar ()) != -1) {
184                                         ch = (char) i;
185                                         
186                                         if (Char.IsDigit (ch) || ch == '.')
187                                                 sb.Append ((char) ReadChar ());
188                                         else
189                                                 break;
190                                 }
191                                 
192                                 token = new Token (sb.ToString (), TokenType.Number, tokenPosition);
193                         } else if (ch == '\'' && position < inputString.Length) {
194                                 StringBuilder sb = new StringBuilder ();
195                                 string temp;
196                                 
197                                 sb.Append (ch);
198                                 bool is_itemref = (PeekChar () == '@');
199                                 int num_open_braces = 0;
200                                 bool in_literal = false;
201                                 
202                                 while ((i = PeekChar ()) != -1) {
203                                         ch = (char) i;
204                                         if (ch == '(' && !in_literal && is_itemref)
205                                                 num_open_braces ++;
206                                         if (ch == ')' && !in_literal && is_itemref)
207                                                 num_open_braces --;
208                                         
209                                         sb.Append ((char) ReadChar ());
210                                         
211                                         if (ch == '\'') {
212                                                 if (num_open_braces == 0)
213                                                         break;
214                                                 in_literal = !in_literal;
215                                         }
216                                 }
217                                 
218                                 temp = sb.ToString ();
219                                 
220                                 token = new Token (temp.Substring (1, temp.Length - 2), TokenType.String, tokenPosition);
221                                 
222                         } else  if (ch == '_' || Char.IsLetter (ch)) {
223                                 StringBuilder sb = new StringBuilder ();
224                                 
225                                 sb.Append ((char) ch);
226                                 
227                                 while ((i = PeekChar ()) != -1) {
228                                         if ((char) i == '_' || Char.IsLetterOrDigit ((char) i))
229                                                 sb.Append ((char) ReadChar ());
230                                         else
231                                                 break;
232                                 }
233                                 
234                                 string temp = sb.ToString ();
235                                 
236                                 if (keywords.ContainsKey (temp))
237                                         token = new Token (temp, keywords [temp], tokenPosition);
238                                 else
239                                         token = new Token (temp, TokenType.String, tokenPosition);
240                                         
241                         } else if (ch == '!' && PeekChar () == (int) '=') {
242                                 token = new Token ("!=", TokenType.NotEqual, tokenPosition);
243                                 ReadChar ();
244                         } else if (ch == '<' && PeekChar () == (int) '=') {
245                                 token = new Token ("<=", TokenType.LessOrEqual, tokenPosition);
246                                 ReadChar ();
247                         } else if (ch == '>' && PeekChar () == (int) '=') {
248                                 token = new Token (">=", TokenType.GreaterOrEqual, tokenPosition);
249                                 ReadChar ();
250                         } else if (ch == '=' && PeekChar () == (int) '=') {
251                                 token = new Token ("==", TokenType.Equal, tokenPosition);
252                                 ReadChar ();
253                         } else if (ch >= 32 && ch < 128) {
254                                 if (charIndexToTokenType [ch] != TokenType.Invalid) {
255                                         token = new Token (new String (ch, 1), charIndexToTokenType [ch], tokenPosition);
256                                         return;
257                                 } else
258                                         throw new ExpressionParseException (String.Format ("Invalid punctuation: {0}", ch));
259                         } else
260                                 throw new ExpressionParseException (String.Format ("Invalid token: {0}", ch));
261                 }
262                 
263                 public int TokenPosition {
264                         get { return tokenPosition; }
265                 }
266                 
267                 public Token Token {
268                         get { return token; }
269                 }
270                 
271 /*
272                 public bool IgnoreWhiteSpace {
273                         get { return ignoreWhiteSpace; }
274                         set { ignoreWhiteSpace = value; }
275                 }
276 */
277                 
278                 struct CharToTokenType {
279                         public char ch;
280                         public TokenType tokenType;
281                         
282                         public CharToTokenType (char ch, TokenType tokenType)
283                         {
284                                 this.ch = ch;
285                                 this.tokenType = tokenType;
286                         }
287                 }
288                 
289                 static CharToTokenType[] charToTokenType = {
290                         new CharToTokenType ('<', TokenType.Less),
291                         new CharToTokenType ('>', TokenType.Greater),
292                         new CharToTokenType ('=', TokenType.Equal),
293                         new CharToTokenType ('(', TokenType.LeftParen),
294                         new CharToTokenType (')', TokenType.RightParen),
295                         new CharToTokenType ('.', TokenType.Dot),
296                         new CharToTokenType (',', TokenType.Comma),
297                         new CharToTokenType ('!', TokenType.Not),
298                         new CharToTokenType ('@', TokenType.Item),
299                         new CharToTokenType ('$', TokenType.Property),
300                         new CharToTokenType ('%', TokenType.Metadata),
301                         new CharToTokenType ('\'', TokenType.Apostrophe),
302                 };
303         }
304 }
305
306 #endif