2 // Mono.MonoBASIC.Tokenizer.cs: The Tokenizer for the MonoBASIC compiler
4 // Author: A Rafael D Teixeira (rafaelteixeirabr@hotmail.com)
6 // Based on cs-tokenizer.cs by Miguel de Icaza (miguel@gnu.org)
8 // Licensed under the terms of the GNU GPL
10 // Copyright (C) 2001 A Rafael D Teixeira
13 namespace Mono.MonoBASIC
17 using System.Collections;
19 using System.Globalization;
24 /// Tokenizer for MonoBASIC source code.
27 public class Tokenizer : yyParser.yyInput
30 // TODO: public SourceFile file_name;
31 public string file_name;
32 public string ref_name;
33 public int ref_line = 1;
36 public int current_token = Token.EOL;
37 bool handle_get_set = false;
39 public int ExpandedTabsSize = 4;
41 public string location {
45 if (current_token == Token.ERROR)
46 det = "detail: " + error_details;
50 return "Line: "+line+" Col: "+col + "\n" +
51 "VirtLine: "+ref_line +
52 " Token: "+current_token + " " + det;
56 public bool properties {
58 return handle_get_set;
62 handle_get_set = value;
69 static Hashtable keywords;
70 static NumberStyles styles;
71 static NumberFormatInfo csharp_format_info;
79 const int TAKEN_BEFORE = 2;
80 const int ELSE_SEEN = 4;
81 const int PARENT_TAKING = 8;
82 const int REGION = 16;
85 // pre-processor if stack state:
90 // Values for the associated token returned
92 System.Text.StringBuilder number;
97 // Details about the error encoutered by the tokenizer
101 public string error {
103 return error_details;
119 static void initTokens ()
121 keywords = new Hashtable ();
123 keywords.Add ("addhandler", Token.ADDHANDLER);
124 keywords.Add ("addressof", Token.ADDRESSOF);
125 keywords.Add ("alias", Token.ALIAS);
126 keywords.Add ("and", Token.AND);
127 keywords.Add ("andalso", Token.ANDALSO);
128 keywords.Add ("ansi", Token.ANSI);
129 keywords.Add ("as", Token.AS);
130 keywords.Add ("assembly", Token.ASSEMBLY);
131 keywords.Add ("auto", Token.AUTO);
132 keywords.Add ("binary", Token.BINARY);
133 keywords.Add ("boolean", Token.BOOLEAN);
134 keywords.Add ("byref", Token.BYREF);
135 keywords.Add ("byte", Token.BYTE);
136 keywords.Add ("byval", Token.BYVAL);
137 keywords.Add ("call", Token.CALL);
138 keywords.Add ("case", Token.CASE);
139 keywords.Add ("catch", Token.CATCH);
140 keywords.Add ("cbool", Token.CBOOL);
141 keywords.Add ("cbyte", Token.CBYTE);
142 keywords.Add ("cchar", Token.CCHAR);
143 keywords.Add ("cdate", Token.CDATE);
144 keywords.Add ("cdec", Token.CDEC);
145 keywords.Add ("cdbl", Token.CDBL);
146 keywords.Add ("char", Token.CHAR);
147 keywords.Add ("cint", Token.CINT);
148 keywords.Add ("class", Token.CLASS);
149 keywords.Add ("clng", Token.CLNG);
150 keywords.Add ("cobj", Token.COBJ);
151 keywords.Add ("compare", Token.COMPARE);
152 keywords.Add ("const", Token.CONST);
153 keywords.Add ("cshort", Token.CSHORT);
154 keywords.Add ("csng", Token.CSNG);
155 keywords.Add ("cstr", Token.CSTR);
156 keywords.Add ("ctype", Token.CTYPE);
157 //keywords.Add ("date", Token.DATE);
158 keywords.Add ("decimal", Token.DECIMAL);
159 keywords.Add ("declare", Token.DECLARE);
160 keywords.Add ("default", Token.DEFAULT);
161 keywords.Add ("delegate", Token.DELEGATE);
162 keywords.Add ("dim", Token.DIM);
163 keywords.Add ("do", Token.DO);
164 keywords.Add ("double", Token.DOUBLE);
165 keywords.Add ("each", Token.EACH);
166 keywords.Add ("else", Token.ELSE);
167 keywords.Add ("elseif", Token.ELSEIF);
168 keywords.Add ("end", Token.END);
169 keywords.Add ("enum", Token.ENUM);
170 keywords.Add ("erase", Token.ERASE);
171 keywords.Add ("error", Token.ERROR);
172 keywords.Add ("event", Token.EVENT);
173 keywords.Add ("exit", Token.EXIT);
174 keywords.Add ("explicit", Token.EXPLICIT);
175 keywords.Add ("false", Token.FALSE);
176 keywords.Add ("finally", Token.FINALLY);
177 keywords.Add ("for", Token.FOR);
178 keywords.Add ("friend", Token.FRIEND);
179 keywords.Add ("function", Token.FUNCTION);
180 keywords.Add ("get", Token.GET);
181 //keywords.Add ("gettype", Token.GETTYPE);
182 keywords.Add ("goto", Token.GOTO);
183 keywords.Add ("handles", Token.HANDLES);
184 keywords.Add ("if", Token.IF);
185 keywords.Add ("implements", Token.IMPLEMENTS);
186 keywords.Add ("imports", Token.IMPORTS);
187 keywords.Add ("in", Token.IN);
188 keywords.Add ("inherits", Token.INHERITS);
189 keywords.Add ("integer", Token.INTEGER);
190 keywords.Add ("interface", Token.INTERFACE);
191 keywords.Add ("is", Token.IS);
192 keywords.Add ("let ", Token.LET );
193 keywords.Add ("lib ", Token.LIB );
194 keywords.Add ("like ", Token.LIKE );
195 keywords.Add ("long", Token.LONG);
196 keywords.Add ("loop", Token.LOOP);
197 keywords.Add ("me", Token.ME);
198 keywords.Add ("mod", Token.MOD);
199 keywords.Add ("module", Token.MODULE);
200 keywords.Add ("mustinherit", Token.MUSTINHERIT);
201 keywords.Add ("mustoverride", Token.MUSTOVERRIDE);
202 keywords.Add ("mybase", Token.MYBASE);
203 keywords.Add ("myclass", Token.MYCLASS);
204 keywords.Add ("namespace", Token.NAMESPACE);
205 keywords.Add ("new", Token.NEW);
206 keywords.Add ("next", Token.NEXT);
207 keywords.Add ("not", Token.NOT);
208 keywords.Add ("nothing", Token.NOTHING);
209 keywords.Add ("notinheritable", Token.NOTINHERITABLE);
210 keywords.Add ("notoverridable", Token.NOTOVERRIDABLE);
211 keywords.Add ("object", Token.OBJECT);
212 keywords.Add ("off", Token.OFF);
213 keywords.Add ("on", Token.ON);
214 keywords.Add ("option", Token.OPTION);
215 keywords.Add ("optional", Token.OPTIONAL);
216 keywords.Add ("or", Token.OR);
217 keywords.Add ("orelse", Token.ORELSE);
218 keywords.Add ("overloads", Token.OVERLOADS);
219 keywords.Add ("overridable", Token.OVERRIDABLE);
220 keywords.Add ("overrides", Token.OVERRIDES);
221 keywords.Add ("paramarray", Token.PARAM_ARRAY);
222 keywords.Add ("preserve", Token.PRESERVE);
223 keywords.Add ("private", Token.PRIVATE);
224 keywords.Add ("property", Token.PROPERTY);
225 keywords.Add ("protected", Token.PROTECTED);
226 keywords.Add ("public", Token.PUBLIC);
227 keywords.Add ("raiseevent", Token.RAISEEVENT);
228 keywords.Add ("readonly", Token.READONLY);
229 keywords.Add ("redim", Token.REDIM);
230 keywords.Add ("rem", Token.REM);
231 keywords.Add ("removehandler", Token.REMOVEHANDLER);
232 keywords.Add ("resume", Token.RESUME);
233 keywords.Add ("return", Token.RETURN);
234 keywords.Add ("select", Token.SELECT);
235 keywords.Add ("set", Token.SET);
236 keywords.Add ("shadows", Token.SHADOWS);
237 keywords.Add ("shared", Token.SHARED);
238 keywords.Add ("short", Token.SHORT);
239 keywords.Add ("single", Token.SINGLE);
240 keywords.Add ("sizeof", Token.SIZEOF);
241 keywords.Add ("static", Token.STATIC);
242 keywords.Add ("step", Token.STEP);
243 keywords.Add ("stop", Token.STOP);
244 keywords.Add ("strict", Token.STRICT);
245 keywords.Add ("string", Token.STRING);
246 keywords.Add ("structure", Token.STRUCTURE);
247 keywords.Add ("sub", Token.SUB);
248 keywords.Add ("synclock", Token.SYNCLOCK);
249 keywords.Add ("text", Token.TEXT);
250 keywords.Add ("then", Token.THEN);
251 keywords.Add ("throw", Token.THROW);
252 keywords.Add ("to", Token.TO);
253 keywords.Add ("true", Token.TRUE);
254 keywords.Add ("try", Token.TRY);
255 keywords.Add ("typeof", Token.TYPEOF);
256 keywords.Add ("unicode", Token.UNICODE);
257 keywords.Add ("until", Token.UNTIL);
258 keywords.Add ("variant", Token.VARIANT);
259 keywords.Add ("when", Token.WHEN);
260 keywords.Add ("while", Token.WHILE);
261 keywords.Add ("with", Token.WITH);
262 keywords.Add ("withevents", Token.WITHEVENTS);
263 keywords.Add ("writeonly", Token.WRITEONLY);
264 keywords.Add ("xor", Token.XOR);
266 if (Parser.UseExtendedSyntax){
267 keywords.Add ("yield", Token.YIELD);
278 csharp_format_info = new NumberFormatInfo ();
279 csharp_format_info.CurrencyDecimalSeparator = ".";
280 styles = NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint;
283 bool is_keyword (string name)
287 res = keywords.Contains(name.ToLower());
288 if ((name == "get" || name == "set") && handle_get_set == false)
293 int getKeyword (string name)
295 return (int) (keywords [name.ToLower()]);
298 public Location Location {
300 return new Location (ref_line, col);
304 void define (string def)
306 if (!RootContext.AllDefines.Contains(def)){
307 RootContext.AllDefines [def] = true;
309 if (defines.Contains (def))
311 defines [def] = true;
314 public bool PropertyParsing {
316 return handle_get_set;
320 handle_get_set = value;
324 bool is_identifier_start_character (char c)
326 return Char.IsLetter (c) || c == '_' ;
329 bool is_identifier_part_character (char c)
331 return (Char.IsLetter (c) || Char.IsDigit (c) || c == '_');
334 int is_punct (char c, ref bool doread)
336 int idx = "{}[](),:;~+-*/%&|^!=<>?".IndexOf (c);
344 return Token.OPEN_BRACKET;
346 return Token.CLOSE_BRACKET;
348 return Token.OPEN_BRACE;
350 return Token.CLOSE_BRACE;
352 return Token.OPEN_PARENS;
354 return Token.CLOSE_PARENS;
358 // return Token.COLON;
362 // return Token.OP_CONCAT;
371 t = Token.OP_ADD_ASSIGN;
379 t = Token.OP_CONCAT_ASSIGN;
381 return Token.OP_CONCAT;
387 t = Token.OP_SUB_ASSIGN;
405 return Token.OP_MULT_ASSIGN;
413 return Token.OP_DIV_ASSIGN;
421 return Token.OP_IDIV_ASSIGN;
423 return Token.OP_IDIV;
429 return Token.OP_EXP_ASSIGN;
457 return Token.ATTR_ASSIGN;
464 bool decimal_digits (int c)
467 bool seen_digits = false;
470 number.Append ((char) c);
472 while ((d = peekChar ()) != -1){
473 if (Char.IsDigit ((char)d)){
474 number.Append ((char) d);
483 void hex_digits (int c)
488 number.Append ((char) c);
489 while ((d = peekChar ()) != -1){
490 char e = Char.ToUpper ((char) d);
492 if (Char.IsDigit (e) ||
493 (e >= 'A' && e <= 'F')){
494 number.Append ((char) e);
501 int real_type_suffix (int c)
507 t = Token.LITERAL_SINGLE;
510 t = Token.LITERAL_DOUBLE;
513 t= Token.LITERAL_DECIMAL;
522 int integer_type_suffix (int c)
524 // FIXME: Handle U and L suffixes.
525 // We also need to see in which kind of
526 // Int the thing fits better according to the spec.
527 return Token.LITERAL_INTEGER;
530 void adjust_int (int t)
532 val = new System.Int32();
533 val = System.Int32.Parse (number.ToString (), 0);
536 int adjust_real (int t)
538 string s = number.ToString ();
540 Console.WriteLine (s);
542 case Token.LITERAL_DECIMAL:
543 val = new System.Decimal ();
544 val = System.Decimal.Parse (
545 s, styles, csharp_format_info);
547 case Token.LITERAL_DOUBLE:
548 val = new System.Double ();
549 val = System.Double.Parse (
550 s, styles, csharp_format_info);
552 case Token.LITERAL_SINGLE:
553 val = new System.Double ();
554 val = (float) System.Double.Parse (
555 s, styles, csharp_format_info);
559 val = new System.Double ();
560 val = System.Double.Parse (
561 s, styles, csharp_format_info);
562 t = Token.LITERAL_DOUBLE;
569 // Invoked if we know we have .digits or digits
571 int is_number (int c)
573 bool is_real = false;
574 number = new System.Text.StringBuilder ();
579 if (Char.IsDigit ((char)c)){
580 if (c == '0' && peekChar () == 'x' || peekChar () == 'X'){
583 val = new System.Int32 ();
584 val = System.Int32.Parse (number.ToString (), NumberStyles.HexNumber);
585 return integer_type_suffix (peekChar ());
592 // We need to handle the case of
593 // "1.1" vs "1.string" (LITERAL_SINGLE vs NUMBER DOT IDENTIFIER)
596 if (decimal_digits ('.')){
602 adjust_int (Token.LITERAL_INTEGER);
603 return Token.LITERAL_INTEGER;
607 if (c == 'e' || c == 'E'){
614 number.Append ((char) c);
617 } else if (c == '-'){
618 number.Append ((char) c);
626 type = real_type_suffix (c);
627 if (type == Token.NONE && !is_real){
628 type = integer_type_suffix (c);
636 return adjust_real (type);
638 Console.WriteLine ("This should not be reached");
639 throw new Exception ("Is Number should never reach this point");
649 if (putback_char != -1){
650 int x = putback_char;
655 return reader.Read ();
660 if (putback_char != -1)
662 return reader.Peek ();
667 if (putback_char != -1)
668 throw new Exception ("This should not happen putback on putback");
672 public bool advance ()
674 return current_token != Token.EOF ;
677 public Object Value {
683 public Object value ()
688 private bool IsEOL(int currentChar)
690 if (currentChar == 0x0D)
692 if (peekChar() == 0x0A) // if it is a CR-LF pair consume LF also
697 return (currentChar == -1 || currentChar == 0x0A || currentChar == 0x2028 || currentChar == 0x2029);
700 private int DropComments()
703 while (!IsEOL(d = getChar ()))
714 int lastToken = current_token;
717 current_token = xtoken ();
718 if (current_token == 0)
720 if (current_token == Token.REM)
721 current_token = DropComments();
722 } while (lastToken == Token.EOL && current_token == Token.EOL);
724 return current_token;
727 private string GetIdentifier()
730 if (is_identifier_start_character ((char) c))
731 return GetIdentifier(c);
736 private string GetIdentifier(int c)
738 System.Text.StringBuilder id = new System.Text.StringBuilder ();
740 id.Append ((char) c);
742 while ((c = peekChar ()) != -1)
744 if (is_identifier_part_character ((char) c))
746 id.Append ((char)getChar ());
753 return id.ToString ();
756 private bool tokens_seen = false;
765 for (;(c = getChar ()) != -1; col++) {
767 // Handle line comments.
771 // Handle line continuation character
776 if (!is_identifier_part_character((char)d)) {
777 while ((c = getChar ()) != -1 && !IsEOL(c)) {}
788 if (current_token == Token.EOL) // if last token was also EOL keep skipping
793 // Handle escaped identifiers
796 if ((val = GetIdentifier()) == null)
798 if ((c = getChar()) != ']')
801 return Token.IDENTIFIER;
804 // Handle unescaped identifiers
805 if (is_identifier_start_character ((char) c))
808 if ((id = GetIdentifier(c)) == null)
812 if (is_keyword(id) && (current_token != Token.DOT))
813 return getKeyword(id);
814 return Token.IDENTIFIER;
817 // handle numeric literals
821 if (Char.IsDigit ((char) peekChar ()))
822 return is_number (c);
826 if (Char.IsDigit ((char) c))
829 return is_number (c);
832 if (c == '#' && !tokens_seen)
838 cont = handle_preprocessing_directive (cont);
847 bool skipping = false;
848 for (;(c = getChar ()) != -1; col++)
857 else if (c == ' ' || c == '\t' || c == '\v' || c == '\r' || c == 0xa0)
864 if (c == '#' && !skipping)
869 Report.Error (1027, Location, "#endif/#endregion expected");
873 if ((t = is_punct ((char)c, ref doread)) != Token.ERROR){
882 // Treat string literals
884 System.Text.StringBuilder s = new System.Text.StringBuilder ();
888 while ((c = getChar ()) != -1){
890 if (peekChar() == '"')
894 return Token.LITERAL_STRING;
905 // expand tabs for location and ignore it as whitespace
908 col = (((col + ExpandedTabsSize) / ExpandedTabsSize) * ExpandedTabsSize) - 1;
913 if (c == ' ' || c == '\f' || c == '\v')
916 error_details = ((char)c).ToString ();
921 if (current_token != Token.EOL) // if last token wasn't EOL send it before EOF
927 public void cleanup ()
929 /* borrowed from mcs - have to work it to have preprocessing in mbas
931 if (ifstack != null && ifstack.Count >= 1) {
932 int state = (int) ifstack.Pop ();
933 if ((state & REGION) != 0)
934 Report.Error (1038, "#endregion directive expected");
936 Report.Error (1027, "#endif directive expected");
941 public Tokenizer (System.IO.TextReader input, string fname, ArrayList defines)
943 this.ref_name = fname;
947 Location.Push (fname);
950 static StringBuilder static_cmd_arg = new System.Text.StringBuilder ();
952 void get_cmd_arg (out string cmd, out string arg)
958 static_cmd_arg.Length = 0;
960 while ((c = getChar ()) != -1 && (c != '\n') && (c != ' ') && (c != '\t') && (c != '\r')){
961 static_cmd_arg.Append ((char) c);
964 cmd = static_cmd_arg.ToString().ToLower();
970 } else if (c == '\r')
973 // skip over white space
974 while ((c = getChar ()) != -1 && (c != '\n') && ((c == '\r') || (c == ' ') || (c == '\t')))
981 } else if (c == '\r'){
986 static_cmd_arg.Length = 0;
987 static_cmd_arg.Append ((char) c);
989 while ((c = getChar ()) != -1 && (c != '\n') && (c != '\r')){
990 static_cmd_arg.Append ((char) c);
996 } else if (c == '\r')
998 arg = static_cmd_arg.ToString ().Trim ();
1000 if (cmd == "end" && arg.ToLower() == "region") {
1004 if (cmd == "end" && arg.ToLower() == "if") {
1012 // Handles the #line directive
1014 bool PreProcessLine (string arg)
1019 if (arg == "default"){
1021 ref_name = file_name;
1022 Location.Push (ref_name);
1029 if ((pos = arg.IndexOf (' ')) != -1 && pos != 0){
1030 ref_line = System.Int32.Parse (arg.Substring (0, pos));
1033 char [] quotes = { '\"' };
1035 string name = arg.Substring (pos). Trim (quotes);
1036 ref_name = name; // TODO: Synchronize with mcs: Location.LookupFile (name);
1037 Location.Push (ref_name);
1039 ref_line = System.Int32.Parse (arg);
1049 // Handles #define and #undef
1051 void PreProcessDefinition (bool is_define, string arg)
1053 if (arg == "" || arg == "true" || arg == "false"){
1054 Report.Error (1001, Location, "Missing identifer to pre-processor directive");
1058 char[] whitespace = { ' ', '\t' };
1059 if (arg.IndexOfAny (whitespace) != -1){
1060 Report.Error (1025, Location, "Single-line comment or end-of-line expected");
1064 foreach (char c in arg){
1065 if (!Char.IsLetter (c) && (c != '_')){
1066 Report.Error (1001, Location, "Identifier expected");
1072 if (defines == null)
1073 defines = new Hashtable ();
1076 if (defines == null)
1078 if (defines.Contains (arg))
1079 defines.Remove (arg);
1083 bool eval_val (string s)
1090 if (defines == null)
1092 if (defines.Contains (s))
1098 bool pp_primary (ref string s)
1107 s = s.Substring (1);
1108 bool val = pp_expr (ref s);
1109 if (s.Length > 0 && s [0] == ')'){
1110 s = s.Substring (1);
1113 Error_InvalidDirective ();
1117 if (is_identifier_start_character (c)){
1123 if (is_identifier_part_character (c)){
1127 bool v = eval_val (s.Substring (0, j));
1128 s = s.Substring (j);
1131 bool vv = eval_val (s);
1136 Error_InvalidDirective ();
1140 bool pp_unary (ref string s)
1147 if (len > 1 && s [1] == '='){
1148 Error_InvalidDirective ();
1151 s = s.Substring (1);
1152 return ! pp_primary (ref s);
1154 return pp_primary (ref s);
1156 Error_InvalidDirective ();
1161 bool pp_eq (ref string s)
1163 bool va = pp_unary (ref s);
1169 if (len > 2 && s [1] == '='){
1170 s = s.Substring (2);
1171 return va == pp_unary (ref s);
1173 Error_InvalidDirective ();
1176 } else if (s [0] == '!' && len > 1 && s [1] == '='){
1177 s = s.Substring (2);
1179 return va != pp_unary (ref s);
1188 bool pp_and (ref string s)
1190 bool va = pp_eq (ref s);
1196 if (len > 2 && s [1] == '&'){
1197 s = s.Substring (2);
1198 return (va & pp_eq (ref s));
1200 Error_InvalidDirective ();
1209 // Evaluates an expression for `#if' or `#elif'
1211 bool pp_expr (ref string s)
1213 bool va = pp_and (ref s);
1220 if (len > 2 && s [1] == '|'){
1221 s = s.Substring (2);
1222 return va | pp_expr (ref s);
1224 Error_InvalidDirective ();
1233 bool eval (string s)
1235 bool v = pp_expr (ref s);
1238 Error_InvalidDirective ();
1245 void Error_InvalidDirective ()
1247 Report.Error (1517, Location, "Invalid pre-processor directive");
1250 void Error_UnexpectedDirective (string extra)
1254 "Unexpected processor directive (" + extra + ")");
1257 void Error_TokensSeen ()
1261 "Cannot define or undefine pre-processor symbols after a token in the file");
1265 // if true, then the code continues processing the code
1266 // if false, the code stays in a loop until another directive is
1269 bool handle_preprocessing_directive (bool caller_is_taking)
1271 char [] blank = { ' ', '\t' };
1273 bool region_directive = false;
1275 get_cmd_arg (out cmd, out arg);
1276 // Eat any trailing whitespaces and single-line comments
1277 if (arg.IndexOf ("//") != -1)
1278 arg = arg.Substring (0, arg.IndexOf ("//"));
1279 arg = arg.TrimEnd (' ', '\t');
1282 // The first group of pre-processing instructions is always processed
1284 switch (cmd.ToLower()){
1286 if (!PreProcessLine (arg))
1289 "Argument to #line directive is missing or invalid");
1293 region_directive = true;
1298 region_directive = true;
1303 Error_InvalidDirective ();
1306 bool taking = false;
1307 if (ifstack == null)
1308 ifstack = new Stack ();
1310 if (ifstack.Count == 0){
1313 int state = (int) ifstack.Peek ();
1314 if ((state & TAKING) != 0)
1318 if (eval (arg) && taking){
1319 int push = TAKING | TAKEN_BEFORE | PARENT_TAKING;
1320 if (region_directive)
1322 ifstack.Push (push);
1325 int push = (taking ? PARENT_TAKING : 0);
1326 if (region_directive)
1328 ifstack.Push (push);
1333 if (ifstack == null || ifstack.Count == 0){
1334 Error_UnexpectedDirective ("no #if for this #end if");
1337 int pop = (int) ifstack.Pop ();
1339 if (region_directive && ((pop & REGION) == 0))
1340 Report.Error (1027, Location, "#end if directive expected");
1341 else if (!region_directive && ((pop & REGION) != 0))
1342 Report.Error (1038, Location, "#end region directive expected");
1344 if (ifstack.Count == 0)
1347 int state = (int) ifstack.Peek ();
1349 if ((state & TAKING) != 0)
1357 if (ifstack == null || ifstack.Count == 0){
1358 Error_UnexpectedDirective ("no #if for this #elif");
1361 int state = (int) ifstack.Peek ();
1363 if ((state & REGION) != 0) {
1364 Report.Error (1038, Location, "#end region directive expected");
1368 if ((state & ELSE_SEEN) != 0){
1369 Error_UnexpectedDirective ("#elif not valid after #else");
1373 if ((state & (TAKEN_BEFORE | TAKING)) != 0)
1376 if (eval (arg) && ((state & PARENT_TAKING) != 0)){
1377 state = (int) ifstack.Pop ();
1378 ifstack.Push (state | TAKING | TAKEN_BEFORE);
1385 if (ifstack == null || ifstack.Count == 0){
1388 "Unexpected processor directive (no #if for this #else)");
1391 int state = (int) ifstack.Peek ();
1393 if ((state & REGION) != 0) {
1394 Report.Error (1038, Location, "#end region directive expected");
1398 if ((state & ELSE_SEEN) != 0){
1399 Error_UnexpectedDirective ("#else within #else");
1406 if ((state & TAKEN_BEFORE) == 0){
1407 ret = ((state & PARENT_TAKING) != 0);
1416 ifstack.Push (state | ELSE_SEEN);
1423 // These are only processed if we are in a `taking' block
1425 if (!caller_is_taking)
1428 switch (cmd.ToLower()){
1430 /* if (any_token_seen){
1431 Error_TokensSeen ();
1434 PreProcessDefinition (true, arg);
1438 /* if (any_token_seen){
1439 Error_TokensSeen ();
1442 PreProcessDefinition (false, arg);
1446 Report.Error (1029, Location, "#error: '" + arg + "'");
1450 Report.Warning (1030, Location, "#warning: '" + arg + "'");
1454 Report.Error (1024, Location, "Preprocessor directive expected (got: " + cmd + ")");