tools/incparser/IncParser.cs
branchrefac-jit
changeset 2284 026da5437111
parent 2192 7602d7fb60d9
child 2288 15c77b21589a
     1.1 --- a/tools/incparser/IncParser.cs	Fri Jul 11 06:51:21 2008 +0000
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,1342 +0,0 @@
     1.4 -using System;
     1.5 -using System.Collections.Generic;
     1.6 -using System.IO;
     1.7 -using System.Text;
     1.8 -
     1.9 -namespace incparser
    1.10 -{
    1.11 -    enum LexToken
    1.12 -    {
    1.13 -        TOKEN_NONE,
    1.14 -        TOKEN_INCLUDE,
    1.15 -        TOKEN_DEFINE,
    1.16 -        TOKEN_CONST,
    1.17 -        TOKEN_STRUCT,
    1.18 -        TOKEN_FUNCTAG,
    1.19 -        TOKEN_FUNCENUM,
    1.20 -        TOKEN_ENUM,
    1.21 -        TOKEN_NATIVE,
    1.22 -        TOKEN_STOCK,
    1.23 -        TOKEN_PUBLIC,
    1.24 -        TOKEN_FORWARD,
    1.25 -        TOKEN_QUOTCHAR,
    1.26 -        TOKEN_OPERATOR,
    1.27 -        TOKEN_CHARACTER,
    1.28 -        /*TOKEN_STRING,*/
    1.29 -        TOKEN_LABEL,
    1.30 -        TOKEN_SYMBOL,
    1.31 -        TOKEN_DOCBLOCK,
    1.32 -        TOKEN_EOF,
    1.33 -    }
    1.34 -
    1.35 -    class ParseException : System.Exception
    1.36 -    {
    1.37 -        public ParseException(string message) : base(message)
    1.38 -        {
    1.39 -        }
    1.40 -    };
    1.41 -         
    1.42 -    class KeywordToken
    1.43 -    {
    1.44 -        public KeywordToken(string k, LexToken t)
    1.45 -        {
    1.46 -            keyword = k;
    1.47 -            token = t;
    1.48 -        }
    1.49 -        public string keyword;
    1.50 -        public LexToken token;
    1.51 -    };
    1.52 -
    1.53 -    class Tokenizer
    1.54 -    {
    1.55 -        private static bool s_initialized = false;
    1.56 -        private static int s_position = 0;
    1.57 -        private static KeywordToken [] s_tokens = null;
    1.58 -        public static KeywordToken[] Tokens = null;
    1.59 -
    1.60 -        public static void Initialize()
    1.61 -        {
    1.62 -            if (s_initialized)
    1.63 -            {
    1.64 -                return;
    1.65 -            }
    1.66 -            s_tokens = new KeywordToken[12];
    1.67 -            s_initialized = true;
    1.68 -            s_position = 0;
    1.69 -
    1.70 -            AddToken("#include", LexToken.TOKEN_INCLUDE);
    1.71 -            AddToken("#define", LexToken.TOKEN_DEFINE);
    1.72 -            AddToken("native", LexToken.TOKEN_NATIVE);
    1.73 -            AddToken("functag", LexToken.TOKEN_FUNCTAG);
    1.74 -            AddToken("funcenum", LexToken.TOKEN_FUNCENUM);
    1.75 -            AddToken("enum", LexToken.TOKEN_ENUM);
    1.76 -            AddToken("stock", LexToken.TOKEN_STOCK);
    1.77 -            AddToken("public", LexToken.TOKEN_PUBLIC);
    1.78 -            AddToken("forward", LexToken.TOKEN_FORWARD);
    1.79 -            AddToken("const", LexToken.TOKEN_CONST);
    1.80 -            AddToken("struct", LexToken.TOKEN_STRUCT);
    1.81 -            AddToken("operator", LexToken.TOKEN_OPERATOR);
    1.82 -
    1.83 -            Tokens = s_tokens;
    1.84 -        }
    1.85 -
    1.86 -        private static void AddToken(string lex, LexToken tok)
    1.87 -        {
    1.88 -            s_tokens[s_position] = new KeywordToken(lex, tok);
    1.89 -            s_position++;
    1.90 -        }
    1.91 -    };
    1.92 -
    1.93 -    class IncParser
    1.94 -    {
    1.95 -        private string FileName;
    1.96 -        private StringBuilder Contents;
    1.97 -        private bool LexPushed;
    1.98 -        private LexToken _LastToken;
    1.99 -        private string _LexString;
   1.100 -        private char _LexChar;
   1.101 -        private uint LineNo;
   1.102 -
   1.103 -        public string LexString
   1.104 -        {
   1.105 -            get
   1.106 -            {
   1.107 -                return _LexString;
   1.108 -            }
   1.109 -        }
   1.110 -
   1.111 -        public char LexChar
   1.112 -        {
   1.113 -            get
   1.114 -            {
   1.115 -                return _LexChar;
   1.116 -            }
   1.117 -        }
   1.118 -
   1.119 -        public uint GetLineNumber()
   1.120 -        {
   1.121 -            return LineNo;
   1.122 -        }
   1.123 -
   1.124 -        public IncParser(string file)
   1.125 -        {
   1.126 -            FileName = file;
   1.127 -
   1.128 -            /* Clear out lexer stuff */
   1.129 -            LexPushed = false;
   1.130 -            _LastToken = LexToken.TOKEN_NONE;
   1.131 -            _LexString = null;
   1.132 -            _LexChar = '\0';
   1.133 -            LineNo = 1;
   1.134 -
   1.135 -            /* Initialize; this can throw an exception */
   1.136 -            Initialize();
   1.137 -        }
   1.138 -
   1.139 -         public void Parse(ParseWriter w)
   1.140 -        {
   1.141 -            w.BeginSection(System.IO.Path.GetFileName(FileName));
   1.142 -            LexToken tok = LexToken.TOKEN_NONE;
   1.143 -            while ((tok = lex()) != LexToken.TOKEN_EOF)
   1.144 -            {
   1.145 -                switch (tok)
   1.146 -                {
   1.147 -                    case LexToken.TOKEN_DOCBLOCK:
   1.148 -                        {
   1.149 -                            w.WritePair("doc", LexString);
   1.150 -                            break;
   1.151 -                        }
   1.152 -                    case LexToken.TOKEN_DEFINE:
   1.153 -                        {
   1.154 -                            PARSE_Define(w);
   1.155 -                            break;
   1.156 -                        }
   1.157 -                    case LexToken.TOKEN_ENUM:
   1.158 -                        {
   1.159 -                            PARSE_Enum(w);
   1.160 -                            break;
   1.161 -                        }
   1.162 -                    case LexToken.TOKEN_FORWARD:
   1.163 -                        {
   1.164 -                            PARSE_Function(tok, w);
   1.165 -                            break;
   1.166 -                        }
   1.167 -                    case LexToken.TOKEN_NATIVE:
   1.168 -                        {
   1.169 -                            PARSE_Function(tok, w);
   1.170 -                            break;
   1.171 -                        }
   1.172 -                    case LexToken.TOKEN_STOCK:
   1.173 -                        {
   1.174 -                            PARSE_Function(tok, w);
   1.175 -                            break;
   1.176 -                        }
   1.177 -                    case LexToken.TOKEN_FUNCTAG:
   1.178 -                        {
   1.179 -                            PARSE_FuncTag(w);
   1.180 -                            break;
   1.181 -                        }
   1.182 -                    case LexToken.TOKEN_FUNCENUM:
   1.183 -                        {
   1.184 -                            PARSE_FuncEnum(w);
   1.185 -                            break;
   1.186 -                        }
   1.187 -                    case LexToken.TOKEN_INCLUDE:
   1.188 -                        {
   1.189 -                            PARSE_Include(w);
   1.190 -                            break;
   1.191 -                        }
   1.192 -                    case LexToken.TOKEN_STRUCT:
   1.193 -                        {
   1.194 -                            PARSE_Struct(w);
   1.195 -                            break;
   1.196 -                        }
   1.197 -                    case LexToken.TOKEN_PUBLIC:
   1.198 -                        {
   1.199 -                            PARSE_Public(w);
   1.200 -                            break;
   1.201 -                        }
   1.202 -                    default:
   1.203 -                        {
   1.204 -                            if (_LexString == "static" || _LexString == "new")
   1.205 -                            {
   1.206 -                                PARSE_Public(w);
   1.207 -                                break;
   1.208 -                            }
   1.209 -                            throw new ParseException("Unrecognized token: " + tok + " " + _LexString);
   1.210 -                        }
   1.211 -                }
   1.212 -            }
   1.213 -            w.EndSection();
   1.214 -        }
   1.215 -
   1.216 -        private void PARSE_Public(ParseWriter w)
   1.217 -        {
   1.218 -            MatchToken(LexToken.TOKEN_CONST);
   1.219 -
   1.220 -            /* Eat up an optional tag */
   1.221 -            MatchToken(LexToken.TOKEN_LABEL);
   1.222 -
   1.223 -            /* Eat up a name */
   1.224 -            NeedToken(LexToken.TOKEN_SYMBOL);
   1.225 -
   1.226 -            while (MatchChar('['))
   1.227 -            {
   1.228 -                DiscardUntilChar(']');
   1.229 -                NeedChar(']');
   1.230 -            }
   1.231 -
   1.232 -            if (MatchChar('='))
   1.233 -            {
   1.234 -                ignore_block();
   1.235 -            }
   1.236 -            else if (MatchChar('(') && MatchChar(')'))
   1.237 -            {
   1.238 -                ignore_block();
   1.239 -                return;
   1.240 -            }
   1.241 -
   1.242 -            NeedChar(';');
   1.243 -        }
   1.244 -
   1.245 -        private void PARSE_Struct(ParseWriter w)
   1.246 -        {
   1.247 -            /* For now, we completely ignore these (they're not written to the output) */
   1.248 -            NeedToken(LexToken.TOKEN_SYMBOL);
   1.249 -            w.structList.Add(LexString);
   1.250 -            NeedChar('{');
   1.251 -
   1.252 -            bool need_closebrace = true;
   1.253 -            bool more_entries = true;
   1.254 -            do
   1.255 -            {
   1.256 -                if (MatchChar('}'))
   1.257 -                {
   1.258 -                    need_closebrace = false;
   1.259 -                    break;
   1.260 -                }
   1.261 -                MatchToken(LexToken.TOKEN_CONST);
   1.262 -                MatchToken(LexToken.TOKEN_LABEL);
   1.263 -                NeedToken(LexToken.TOKEN_SYMBOL);
   1.264 -                while (MatchChar('['))
   1.265 -                {
   1.266 -                    DiscardUntilChar(']');
   1.267 -                    NeedChar(']');
   1.268 -                }
   1.269 -                more_entries = MatchChar(',');
   1.270 -                MatchToken(LexToken.TOKEN_DOCBLOCK);
   1.271 -                if (!more_entries)
   1.272 -                {
   1.273 -                    break;
   1.274 -                }
   1.275 -            } while (true);
   1.276 -            if (need_closebrace)
   1.277 -            {
   1.278 -                NeedChar('}');
   1.279 -            }
   1.280 -            NeedChar(';');
   1.281 -        }
   1.282 -
   1.283 -        private void PARSE_Include(ParseWriter w)
   1.284 -        {
   1.285 -            /* read until the end of the line */
   1.286 -            int index = Contents.ToString().IndexOf('\n');
   1.287 -            string value;
   1.288 -            if (index == -1)
   1.289 -            {
   1.290 -                value = Contents.ToString();
   1.291 -                Contents.Remove(0, value.Length);
   1.292 -            }
   1.293 -            else if (index == 0)
   1.294 -            {
   1.295 -                value = "";
   1.296 -            }
   1.297 -            else
   1.298 -            {
   1.299 -                value = Contents.ToString().Substring(0, index);
   1.300 -                Contents.Remove(0, index);
   1.301 -            }
   1.302 -
   1.303 -            /* Strip whitespace */
   1.304 -            value = value.Trim('\r', '\t', ' ');
   1.305 -
   1.306 -            /* Write */
   1.307 -            w.BeginSection("include");
   1.308 -            w.WritePair("name", value);
   1.309 -            w.EndSection();
   1.310 -        }
   1.311 -
   1.312 -        private void PARSE_FuncEnum(ParseWriter w)
   1.313 -        {
   1.314 -            w.BeginSection("funcenum");
   1.315 -
   1.316 -            /* Get the functag name */
   1.317 -            NeedToken(LexToken.TOKEN_SYMBOL);
   1.318 -            w.WritePair("name", LexString);
   1.319 -            w.funcenumList.Add(LexString);
   1.320 -
   1.321 -            NeedChar('{');
   1.322 -
   1.323 -            bool need_closebrace = true;
   1.324 -            do
   1.325 -            {
   1.326 -                /* Shortcut out? */
   1.327 -                if (MatchChar('}'))
   1.328 -                {
   1.329 -                    need_closebrace = false;
   1.330 -                    break;
   1.331 -                }
   1.332 -
   1.333 -                /* Start function section */
   1.334 -                w.BeginSection("function");
   1.335 -
   1.336 -                if (MatchToken(LexToken.TOKEN_DOCBLOCK))
   1.337 -                {
   1.338 -                    w.WritePair("doc", LexString);
   1.339 -                }
   1.340 -                
   1.341 -                /* Get the return tag */
   1.342 -                if (MatchToken(LexToken.TOKEN_LABEL))
   1.343 -                {
   1.344 -                    w.WritePair("return", LexString);
   1.345 -                }
   1.346 -
   1.347 -                /* Get function type */
   1.348 -                if (MatchToken(LexToken.TOKEN_PUBLIC))
   1.349 -                {
   1.350 -                    w.WritePair("type", "public");
   1.351 -                }
   1.352 -                else if (MatchToken(LexToken.TOKEN_STOCK))
   1.353 -                {
   1.354 -                    w.WritePair("type", "stock");
   1.355 -                }
   1.356 -                
   1.357 -                /* Parse the parameters */
   1.358 -                ParseParameters(w);
   1.359 -
   1.360 -                /* End the section */
   1.361 -                w.EndSection();
   1.362 -
   1.363 -                if (!MatchChar(','))
   1.364 -                {
   1.365 -                    break;
   1.366 -                }
   1.367 -            } while (true);
   1.368 -
   1.369 -            if (need_closebrace)
   1.370 -            {
   1.371 -                NeedChar('}');
   1.372 -            }
   1.373 -            NeedChar(';');
   1.374 -
   1.375 -            w.EndSection();
   1.376 -        }
   1.377 -
   1.378 -        private void PARSE_FuncTag(ParseWriter w)
   1.379 -        {
   1.380 -            w.BeginSection("functag");
   1.381 -
   1.382 -            /* Get the functag name */
   1.383 -            NeedToken(LexToken.TOKEN_SYMBOL);
   1.384 -            w.WritePair("name", LexString);
   1.385 -            w.functagList.Add(LexString);
   1.386 -
   1.387 -            if (MatchToken(LexToken.TOKEN_LABEL))
   1.388 -            {
   1.389 -                w.WritePair("return", LexString);
   1.390 -            }
   1.391 -
   1.392 -            if (MatchToken(LexToken.TOKEN_PUBLIC))
   1.393 -            {
   1.394 -                w.WritePair("type", "public");
   1.395 -            }
   1.396 -            else if (MatchToken(LexToken.TOKEN_STOCK))
   1.397 -            {
   1.398 -                w.WritePair("type", "stock");
   1.399 -            }
   1.400 -
   1.401 -            ParseParameters(w);
   1.402 -            NeedChar(';');
   1.403 -            
   1.404 -            w.EndSection();
   1.405 -        }
   1.406 -
   1.407 -        private void PARSE_Function(LexToken tok, ParseWriter w)
   1.408 -        {
   1.409 -            string tag="", name;
   1.410 -
   1.411 -            /* Get the return value */
   1.412 -            if (MatchToken(LexToken.TOKEN_LABEL))
   1.413 -            {
   1.414 -                tag = LexString;
   1.415 -            }
   1.416 -
   1.417 -            if (MatchToken(LexToken.TOKEN_OPERATOR))
   1.418 -            {
   1.419 -                /* Check if we're some sort of invalid function */
   1.420 -                DiscardUntilCharOrComment('(', false);
   1.421 -                ParseParameters(null);
   1.422 -                if (tok == LexToken.TOKEN_STOCK)
   1.423 -                {
   1.424 -                    ignore_block();
   1.425 -                }
   1.426 -                else if (tok == LexToken.TOKEN_NATIVE || tok == LexToken.TOKEN_FORWARD)
   1.427 -                {
   1.428 -                    if (MatchChar('='))
   1.429 -                    {
   1.430 -                        DiscardUntilCharOrComment(';', false);
   1.431 -                    }
   1.432 -                    NeedChar(';');
   1.433 -                }
   1.434 -                return;
   1.435 -            }
   1.436 -
   1.437 -            /* Get the name */
   1.438 -            NeedToken(LexToken.TOKEN_SYMBOL);
   1.439 -            name = LexString;
   1.440 -
   1.441 -            PARSE_Function(tok, w, tag, name);
   1.442 -        }
   1.443 -
   1.444 -        private void PARSE_Function(LexToken tok, ParseWriter w, string tag, string name)
   1.445 -        {
   1.446 -            if (tok == LexToken.TOKEN_FORWARD)
   1.447 -            {
   1.448 -                w.BeginSection("forward");
   1.449 -                w.forwardList.Add(name);
   1.450 -            }
   1.451 -            else if (tok == LexToken.TOKEN_NATIVE)
   1.452 -            {
   1.453 -                w.BeginSection("native");
   1.454 -                w.nativeList.Add(name);
   1.455 -            }
   1.456 -            else if (tok == LexToken.TOKEN_STOCK)
   1.457 -            {
   1.458 -                w.BeginSection("stock");
   1.459 -                w.stockList.Add(name);
   1.460 -            }
   1.461 -
   1.462 -            w.WritePair("name", name);
   1.463 -
   1.464 -            if (tag.Length > 0)
   1.465 -            {
   1.466 -                w.WritePair("return", tag);
   1.467 -            }
   1.468 -
   1.469 -            ParseParameters(w);
   1.470 -
   1.471 -            if (tok == LexToken.TOKEN_STOCK)
   1.472 -            {
   1.473 -                ignore_block();
   1.474 -            }
   1.475 -            else
   1.476 -            {
   1.477 -                /* Make sure there's a semicolon */
   1.478 -                if (MatchChar('='))
   1.479 -                {
   1.480 -                    DiscardUntilCharOrComment(';', false);
   1.481 -                }
   1.482 -                NeedChar(';');
   1.483 -            }
   1.484 -
   1.485 -            w.EndSection();
   1.486 -        }
   1.487 -
   1.488 -        private void ParseParameters(ParseWriter w)
   1.489 -        {
   1.490 -            NeedChar('(');
   1.491 -            string extra;
   1.492 -            do
   1.493 -            {
   1.494 -                if (MatchChar(')'))
   1.495 -                {
   1.496 -                    return;
   1.497 -                }
   1.498 -
   1.499 -                /* Start the parameter */
   1.500 -                if (w != null)
   1.501 -                {
   1.502 -                    w.BeginSection("parameter");
   1.503 -                }
   1.504 -
   1.505 -                /* Check for a 'const' token */
   1.506 -                if (MatchToken(LexToken.TOKEN_CONST) && w != null)
   1.507 -                {
   1.508 -                    w.WritePair("const", "true");
   1.509 -                }
   1.510 -
   1.511 -                /* Check if it's by reference */
   1.512 -                if (MatchChar('&') && w != null)
   1.513 -                {
   1.514 -                    w.WritePair("byref", "true");
   1.515 -                }
   1.516 -
   1.517 -                /* Check for a tag */
   1.518 -                if (MatchToken(LexToken.TOKEN_LABEL) && w != null)
   1.519 -                {
   1.520 -                    w.WritePair("tag", LexString);
   1.521 -                }
   1.522 -
   1.523 -                /* Get the symbol and write it */
   1.524 -                if (MatchString(0, "...") && w != null)
   1.525 -                {
   1.526 -                    w.WritePair("name", "...");
   1.527 -                }
   1.528 -                else
   1.529 -                {
   1.530 -                    NeedToken(LexToken.TOKEN_SYMBOL);
   1.531 -                    if (w != null)
   1.532 -                    {
   1.533 -                        w.WritePair("name", LexString);
   1.534 -                    }
   1.535 -                }
   1.536 -
   1.537 -                /* Check if we have a default value yet */
   1.538 -                bool default_value = false;
   1.539 -                if (MatchChar('='))
   1.540 -                {
   1.541 -                    default_value = true;
   1.542 -                }
   1.543 -                else if (MatchChar('['))
   1.544 -                {
   1.545 -                    extra = "";
   1.546 -                    string temp;
   1.547 -                    do
   1.548 -                    {
   1.549 -                        extra += "[";
   1.550 -                        temp = ConsumeUntilChar(']');
   1.551 -                        if (temp != null)
   1.552 -                        {
   1.553 -                            extra += temp;
   1.554 -                        }
   1.555 -                        extra += "]";
   1.556 -                        NeedChar(']');
   1.557 -                    } while (MatchChar('['));
   1.558 -                    w.WritePair("decoration", extra);
   1.559 -                }
   1.560 -
   1.561 -                /* If we have a default value, get it */
   1.562 -                if (default_value || MatchChar('='))
   1.563 -                {
   1.564 -                    if ((extra = ConsumeParamDefValue()) == null)
   1.565 -                    {
   1.566 -                        throw new ParseException("Expected a default value; found none");
   1.567 -                    }
   1.568 -                    if (w != null)
   1.569 -                    {
   1.570 -                        w.WritePair("defval", extra);
   1.571 -                    }
   1.572 -                }
   1.573 -
   1.574 -                /* End the parameter */
   1.575 -                if (w != null)
   1.576 -                {
   1.577 -                    w.EndSection();
   1.578 -                }
   1.579 -
   1.580 -                if (!MatchChar(','))
   1.581 -                {
   1.582 -                    break;
   1.583 -                }
   1.584 -            } while (true);
   1.585 -
   1.586 -            NeedChar(')');
   1.587 -        }
   1.588 -
   1.589 -        private void PARSE_Enum(ParseWriter w)
   1.590 -        {
   1.591 -            string name = "";
   1.592 -            if (MatchToken(LexToken.TOKEN_SYMBOL))
   1.593 -            {
   1.594 -                name = LexString;
   1.595 -            }
   1.596 -
   1.597 -            w.BeginSection("enum");
   1.598 -            w.WritePair("name", name);
   1.599 -            w.BeginSection("properties");
   1.600 -
   1.601 -            w.enumList.Add(name);
   1.602 -
   1.603 -            NeedChar('{');
   1.604 -            bool more_entries = true;
   1.605 -            bool need_closebrace = true;
   1.606 -
   1.607 -            if (MatchToken(LexToken.TOKEN_DOCBLOCK))
   1.608 -            {
   1.609 -              w.WritePair("doc", LexString);
   1.610 -            }
   1.611 -
   1.612 -            do
   1.613 -            {
   1.614 -                if (MatchChar('}'))
   1.615 -                {
   1.616 -                    need_closebrace = false;
   1.617 -                    break;
   1.618 -                }
   1.619 -                NeedToken(LexToken.TOKEN_SYMBOL);
   1.620 -                name = LexString;
   1.621 - 
   1.622 -                if (MatchChar('='))
   1.623 -                {
   1.624 -                    DiscardUntilCharOrComment(",\n}", true);
   1.625 -                }
   1.626 -                more_entries = MatchChar(',');
   1.627 -                w.WritePair("name", name);
   1.628 -                w.enumTypeList.Add(name);
   1.629 -                if (MatchToken(LexToken.TOKEN_DOCBLOCK))
   1.630 -                {
   1.631 -                    w.WritePair("doc", LexString);
   1.632 -                }
   1.633 -            } while (more_entries);
   1.634 -            if (need_closebrace)
   1.635 -            {
   1.636 -                NeedChar('}');
   1.637 -            }
   1.638 -            NeedChar(';');
   1.639 -            w.EndSection();
   1.640 -            w.EndSection();
   1.641 -        }
   1.642 -
   1.643 -        private void PARSE_Define(ParseWriter w)
   1.644 -        {
   1.645 -            /* first, get the symbol name */
   1.646 -            NeedToken(LexToken.TOKEN_SYMBOL);
   1.647 -            string name = LexString;
   1.648 -            string value;
   1.649 -
   1.650 -            /* read until we hit the end of a line OR a comment */
   1.651 -            int endpoint = -1;
   1.652 -            for (int i = 0; i < Contents.Length; i++)
   1.653 -            {
   1.654 -                if (Contents[i] == '\n')
   1.655 -                {
   1.656 -                    endpoint = i;
   1.657 -                    break;
   1.658 -                }
   1.659 -                else if (CheckString(i, "/**"))
   1.660 -                {
   1.661 -                    endpoint = i;
   1.662 -                    break;
   1.663 -                }
   1.664 -            }
   1.665 -
   1.666 -            if (endpoint < 1)
   1.667 -            {
   1.668 -                value = "";
   1.669 -            }
   1.670 -            else
   1.671 -            {
   1.672 -                value = Contents.ToString().Substring(0, endpoint);
   1.673 -                Contents.Remove(0, endpoint);
   1.674 -            }
   1.675 -
   1.676 -            /* Write */
   1.677 -            w.defineList.Add(name);
   1.678 -
   1.679 -            w.BeginSection("define");
   1.680 -            w.WritePair("name", name);
   1.681 -            w.WritePair("linetext", value);
   1.682 -            w.EndSection();
   1.683 -        }
   1.684 -
   1.685 -        /* Reads up to a character and discards all text before it.
   1.686 -         */
   1.687 -        private void DiscardUntilChar(char c)
   1.688 -        {
   1.689 -            int eol = Contents.ToString().IndexOf(c);
   1.690 -
   1.691 -            if (eol < 1)
   1.692 -            {
   1.693 -                return;
   1.694 -            }
   1.695 -
   1.696 -            Contents.Remove(0, eol);
   1.697 -        }
   1.698 -
   1.699 -        /* Same as DiscardUntilChar, except the discarded
   1.700 -         * text is returned first.
   1.701 -         */
   1.702 -        private string ConsumeUntilChar(char c)
   1.703 -        {
   1.704 -            int eol = Contents.ToString().IndexOf(c);
   1.705 -
   1.706 -            if (eol < 1)
   1.707 -            {
   1.708 -                return null;
   1.709 -            }
   1.710 -
   1.711 -            string rest = Contents.ToString().Substring(0, eol);
   1.712 -            Contents.Remove(0, eol);
   1.713 -            return rest;
   1.714 -        }
   1.715 -
   1.716 -        /**
   1.717 -         * Returns a parameter's default value.
   1.718 -         */
   1.719 -        private string ConsumeParamDefValue()
   1.720 -        {
   1.721 -            int eol = FindEndOfExprLine(0);
   1.722 -            if (eol < 1)
   1.723 -            {
   1.724 -                return null;
   1.725 -            }
   1.726 -
   1.727 -            string rest = Contents.ToString().Substring(0, eol);
   1.728 -            Contents.Remove(0, eol);
   1.729 -            return rest;
   1.730 -        }
   1.731 -
   1.732 -        /**
   1.733 -         * Discards all data up to a certain character, ignoring
   1.734 -         * the contents, unless specified to stop at a doc block comment.
   1.735 -         */
   1.736 -        private void DiscardUntilCharOrComment(char c, bool stop_at_comment)
   1.737 -        {
   1.738 -            for (int i = 0; i < Contents.Length; i++)
   1.739 -            {
   1.740 -                if (Contents[i] == '\n')
   1.741 -                {
   1.742 -                    LineNo++;
   1.743 -                }
   1.744 -                else if (Contents[i] == c)
   1.745 -                {
   1.746 -                    if (i > 0)
   1.747 -                    {
   1.748 -                        Contents.Remove(0, i);
   1.749 -                    }
   1.750 -                    return;
   1.751 -                }
   1.752 -                else if (stop_at_comment && CheckString(i, "/**"))
   1.753 -                {
   1.754 -                    if (i > 0)
   1.755 -                    {
   1.756 -                        Contents.Remove(0, i);
   1.757 -                    }
   1.758 -                    return;
   1.759 -                }
   1.760 -            }
   1.761 -        }
   1.762 -
   1.763 -       /**
   1.764 -        * Discards all data up to a certain character, ignoring
   1.765 -        * the contents, unless specified to stop at a doc block comment.
   1.766 -        */
   1.767 -        private void DiscardUntilCharOrComment(string s, bool stop_at_comment)
   1.768 -        {
   1.769 -          for (int i = 0; i < Contents.Length; i++)
   1.770 -          {
   1.771 -            if (Contents[i] == '\n')
   1.772 -            {
   1.773 -              LineNo++;
   1.774 -            }
   1.775 -            else if (s.Contains(Contents[i].ToString()))
   1.776 -            {
   1.777 -              if (i > 0)
   1.778 -              {
   1.779 -                Contents.Remove(0, i);
   1.780 -              }
   1.781 -              return;
   1.782 -            }
   1.783 -            else if (stop_at_comment && CheckString(i, "/**"))
   1.784 -            {
   1.785 -              if (i > 0)
   1.786 -              {
   1.787 -                Contents.Remove(0, i);
   1.788 -              }
   1.789 -              return;
   1.790 -            }
   1.791 -          }
   1.792 -        }
   1.793 -
   1.794 -        /**
   1.795 -         * Finds the end of an expression
   1.796 -         */
   1.797 -        private int FindEndOfExprLine(int start)
   1.798 -        {
   1.799 -            for (int i = start; i < Contents.Length; i++)
   1.800 -            {
   1.801 -                if (Contents[i] == '{')
   1.802 -                {
   1.803 -                    if ((i = FindEndOfConsumptionLine('}', start+1)) == -1)
   1.804 -                    {
   1.805 -                        throw new ParseException("Expected token: } (found none)");
   1.806 -                    }
   1.807 -                }
   1.808 -                else if (Contents[i] == ')' || Contents[i] == ',')
   1.809 -                {
   1.810 -                    return i;
   1.811 -                }
   1.812 -            }
   1.813 -
   1.814 -            return -1;
   1.815 -        }
   1.816 -
   1.817 -        private int FindEndOfConsumptionLine(char c, int start)
   1.818 -        {
   1.819 -            for (int i = start; i < Contents.Length; i++)
   1.820 -            {
   1.821 -                if (Contents[i] == '{')
   1.822 -                {
   1.823 -                    if ((i = FindEndOfConsumptionLine('}', i + 1)) == -1)
   1.824 -                    {
   1.825 -                        throw new ParseException("Expected token: } (found none)");
   1.826 -                    }
   1.827 -                }
   1.828 -                else if (Contents[i] == c)
   1.829 -                {
   1.830 -                    return i;
   1.831 -                }
   1.832 -            }
   1.833 -
   1.834 -            return -1;
   1.835 -        }
   1.836 -
   1.837 -        private void Initialize()
   1.838 -        {
   1.839 -            /* Open file, read it, and close it */
   1.840 -            StreamReader sr = File.OpenText(FileName);
   1.841 -            Contents = new StringBuilder(sr.ReadToEnd());
   1.842 -            sr.Close();
   1.843 -
   1.844 -            /* Strip comments (may throw an exception) */
   1.845 -            preprocess();
   1.846 -
   1.847 -            /* Lastly, initialize the tokenizer */
   1.848 -            Tokenizer.Initialize();
   1.849 -        }
   1.850 -
   1.851 -        /* Consumes a token iff it matches */
   1.852 -        private bool MatchToken(LexToken token)
   1.853 -        {
   1.854 -            LexToken tok = lex();
   1.855 -            if (tok != token)
   1.856 -            {
   1.857 -                lexpush();
   1.858 -                return false;
   1.859 -            }
   1.860 -            return true;
   1.861 -        }
   1.862 -
   1.863 -        /* Consumes a token and aborts the parser if there is no match */
   1.864 -        private void NeedToken(LexToken token)
   1.865 -        {
   1.866 -            if (!MatchToken(token))
   1.867 -            {
   1.868 -                throw new ParseException("Expected token: " + token);
   1.869 -            }
   1.870 -        }
   1.871 -
   1.872 -        /* Consumes a character iff it matches */
   1.873 -        private bool MatchChar(char c)
   1.874 -        {
   1.875 -            if (lex() != LexToken.TOKEN_CHARACTER)
   1.876 -            {
   1.877 -                lexpush();
   1.878 -                return false;
   1.879 -            }
   1.880 -            if (_LexChar != c)
   1.881 -            {
   1.882 -                lexpush();
   1.883 -                return false;
   1.884 -            }
   1.885 -            return true;
   1.886 -        }
   1.887 -
   1.888 -        /* Consumes a character or aborts the parser if there is no match */
   1.889 -        private void NeedChar(char c)
   1.890 -        {
   1.891 -            if (!MatchChar(c))
   1.892 -            {
   1.893 -                throw new ParseException("Expected character: " + c);
   1.894 -            }
   1.895 -        }
   1.896 -        
   1.897 -        /* Saves the lexer state so we don't reparse unnecessarily */
   1.898 -        private void lexpush()
   1.899 -        {
   1.900 -            if (LexPushed)
   1.901 -            {
   1.902 -                throw new ParseException("Lexer cannot be pushed twice");
   1.903 -            }
   1.904 -            LexPushed = true;
   1.905 -        }
   1.906 -
   1.907 -        /* Attempts to match a string against the next stream tokens.
   1.908 -         * On success, the token stream is advanced.
   1.909 -         */
   1.910 -        private bool MatchString(int startPos, string str)
   1.911 -        {
   1.912 -            if (str.Length > Contents.Length - startPos)
   1.913 -            {
   1.914 -                return false;
   1.915 -            }
   1.916 -            for (int i = 0; i < str.Length; i++)
   1.917 -            {
   1.918 -                if (str[i] != Contents[startPos + i])
   1.919 -                {
   1.920 -                    return false;
   1.921 -                }
   1.922 -            }
   1.923 -            Contents.Remove(startPos, str.Length);
   1.924 -            return true;
   1.925 -        }
   1.926 -
   1.927 -        /* Attempts to match a string against the next stream tokens */
   1.928 -        private bool CheckString(int startPos, string str)
   1.929 -        {
   1.930 -            if (str.Length > Contents.Length - startPos)
   1.931 -            {
   1.932 -                return false;
   1.933 -            }
   1.934 -            for (int i = 0; i < str.Length; i++)
   1.935 -            {
   1.936 -                if (str[i] != Contents[startPos + i])
   1.937 -                {
   1.938 -                    return false;
   1.939 -                }
   1.940 -            }
   1.941 -            return true;
   1.942 -        }
   1.943 -
   1.944 -        /* Ignores a block starting and ending with { and } respectively */
   1.945 -        private void ignore_block()
   1.946 -        {
   1.947 -            /* Hrm, this is tricky.  First, expect an open brace. */
   1.948 -            NeedChar('{');
   1.949 -            /* Consume the entire function by keeping track of braces */
   1.950 -            int numBraces = 1;
   1.951 -            bool in_string = false;
   1.952 -            bool found_end = false;
   1.953 -            for (int i = 0; i < Contents.Length; i++)
   1.954 -            {
   1.955 -                if (Contents[i] == '\n')
   1.956 -                {
   1.957 -                    LineNo++;
   1.958 -                }
   1.959 -                if (!in_string)
   1.960 -                {
   1.961 -                    if (Contents[i] == '"')
   1.962 -                    {
   1.963 -                        in_string = true;
   1.964 -                    }
   1.965 -                    else if (Contents[i] == '{')
   1.966 -                    {
   1.967 -                        numBraces++;
   1.968 -                    }
   1.969 -                    else if (Contents[i] == '}')
   1.970 -                    {
   1.971 -                        if (numBraces == 0)
   1.972 -                        {
   1.973 -                            throw new ParseException("Unable to find a matching open brace");
   1.974 -                        }
   1.975 -                        if (--numBraces == 0)
   1.976 -                        {
   1.977 -                            Contents.Remove(0, i + 1);
   1.978 -                            found_end = true;
   1.979 -                            break;
   1.980 -                        }
   1.981 -                    }
   1.982 -                }
   1.983 -                else
   1.984 -                {
   1.985 -                    /* It is possible to be in a string and at the first character */
   1.986 -                    if (Contents[i] == '"' && Contents[i - 1] != '\\')
   1.987 -                    {
   1.988 -                        in_string = false;
   1.989 -                    }
   1.990 -                }
   1.991 -            }
   1.992 -            if (!found_end)
   1.993 -            {
   1.994 -                throw new ParseException("Unable to find a matching close brace");
   1.995 -            }
   1.996 -        }
   1.997 -
   1.998 -        /* Strips all non-doc C and C++ style comments. as well as unused pragmas */
   1.999 -        private void preprocess()
  1.1000 -        {
  1.1001 -            if (Contents.Length == 1)
  1.1002 -            {
  1.1003 -                return;
  1.1004 -            }
  1.1005 -
  1.1006 -            bool in_comment = false;
  1.1007 -            bool is_ml = false;
  1.1008 -            bool is_doc = false;
  1.1009 -            bool is_newline = true;
  1.1010 -
  1.1011 -            for (int i=0; i<Contents.Length; i++)
  1.1012 -            {
  1.1013 -                if (Contents[i] == '\n')
  1.1014 -                {
  1.1015 -                    is_newline = true;
  1.1016 -                }
  1.1017 -                if (!in_comment)
  1.1018 -                {
  1.1019 -                    if (Contents[i] == '/')
  1.1020 -                    {
  1.1021 -                        if (Contents[i+1] == '/')
  1.1022 -                        {
  1.1023 -                            in_comment = true;
  1.1024 -                            is_ml = false;
  1.1025 -                            is_doc = false;
  1.1026 -                            is_newline = false;
  1.1027 -                        } else if (Contents[i+1] == '*') {
  1.1028 -                            /* Detect whether this is a doc comment or not */
  1.1029 -                            if (Contents.Length - i >= 3
  1.1030 -                                && Contents[i+2] == '*')
  1.1031 -                            {
  1.1032 -                                is_doc = true;
  1.1033 -                            } else {
  1.1034 -                                is_doc = false;
  1.1035 -                            }
  1.1036 -                            in_comment = true;
  1.1037 -                            is_ml = true;
  1.1038 -                        }
  1.1039 -                        if (in_comment && !is_doc)
  1.1040 -                        {
  1.1041 -                            Contents[i] = ' ';
  1.1042 -                            Contents[i+1] = ' ';        /* Just for safety */
  1.1043 -                        }
  1.1044 -                    }
  1.1045 -                    else if (is_newline)
  1.1046 -                    {
  1.1047 -                        if (Contents[i] == '#')
  1.1048 -                        {
  1.1049 -                            if (!CheckString(i, "#define")
  1.1050 -                                && !CheckString(i, "#include"))
  1.1051 -                            {
  1.1052 -                                /* Ignore! */
  1.1053 -                                Contents[i] = ' ';
  1.1054 -                                in_comment = true;
  1.1055 -                                is_doc = false;
  1.1056 -                                is_ml = false;
  1.1057 -                            }
  1.1058 -                            is_newline = false;
  1.1059 -                        }
  1.1060 -                        else if (!Char.IsWhiteSpace(Contents[i]))
  1.1061 -                        {
  1.1062 -                            is_newline = false;
  1.1063 -                        }
  1.1064 -                    }
  1.1065 -                } else {
  1.1066 -                    if (is_ml)
  1.1067 -                    {
  1.1068 -                        if (Contents[i] == '*' && Contents[i+1] == '/')
  1.1069 -                        {
  1.1070 -                            if (!is_doc)
  1.1071 -                            {
  1.1072 -                                Contents[i] = ' ';
  1.1073 -                                Contents[i+1] = ' ';
  1.1074 -                            }
  1.1075 -                            in_comment = false;
  1.1076 -                            i++;    /* Don't look at the next character */
  1.1077 -                        }
  1.1078 -                        else if (!is_doc && Contents[i] != '\n')
  1.1079 -                        {
  1.1080 -                            /* Erase comment */
  1.1081 -                            Contents[i] = ' ';
  1.1082 -                        }
  1.1083 -                    } else {
  1.1084 -                        if (is_newline)
  1.1085 -                        {
  1.1086 -                            in_comment = false;
  1.1087 -                        }
  1.1088 -                        else
  1.1089 -                        {
  1.1090 -                            /* Erase comment */
  1.1091 -                            Contents[i] = ' ';
  1.1092 -                        }
  1.1093 -                    }
  1.1094 -                }
  1.1095 -            }
  1.1096 -
  1.1097 -            if (in_comment)
  1.1098 -            {
  1.1099 -                throw new ParseException("Multi-line comment has no terminator");
  1.1100 -            }
  1.1101 -        }
  1.1102 -
  1.1103 -        /* Strips whitespace */
  1.1104 -        private void trim_whitespace_pre()
  1.1105 -        {
  1.1106 -            int spaces = 0;
  1.1107 -            while (spaces < Contents.Length
  1.1108 -                   && Contents[spaces] != '\0'
  1.1109 -                   && Char.IsWhiteSpace(Contents[spaces]))
  1.1110 -            {
  1.1111 -                if (Contents[spaces] == '\n')
  1.1112 -                {
  1.1113 -                    LineNo++;
  1.1114 -                }
  1.1115 -                spaces++;
  1.1116 -            }
  1.1117 -            if (spaces > 0)
  1.1118 -            {
  1.1119 -                Contents.Remove(0, spaces);
  1.1120 -            }
  1.1121 -        }
  1.1122 -
  1.1123 -        private void preprocess_line()
  1.1124 -        {
  1.1125 -            trim_whitespace_pre();
  1.1126 -        }
  1.1127 -
  1.1128 -        private bool IsSymbolChar(char c, bool first)
  1.1129 -        {
  1.1130 -            bool valid = (first ? Char.IsLetter(c) : Char.IsLetterOrDigit(c));
  1.1131 -            return (valid || (c == '_'));
  1.1132 -        }
  1.1133 -
  1.1134 -        private bool IsEscapedChar(char c)
  1.1135 -        {
  1.1136 -            return (c == 'n'
  1.1137 -                    || c == 'r'
  1.1138 -                    || c == 't'
  1.1139 -                    || c == 'v'
  1.1140 -                    || c == '\\'
  1.1141 -                    || c == '"');
  1.1142 -        }
  1.1143 -
  1.1144 -        private bool IsNotKeywordChar(char c)
  1.1145 -        {
  1.1146 -            return (Char.IsWhiteSpace(c)
  1.1147 -                    || (c == '-' || c == '+')
  1.1148 -                    || (c == '/' || c == '*')
  1.1149 -                    || (c == '(' || c == ')')
  1.1150 -                    || (c == '=' || c == '%')
  1.1151 -                    || (c == '>' || c == '<')
  1.1152 -                    || (c == '!' || c == '~')
  1.1153 -                    );
  1.1154 -        }
  1.1155 -
  1.1156 -        /* Consumes one lexical token and gathers information about it */
  1.1157 -        private LexToken lex()
  1.1158 -        {
  1.1159 -            if (LexPushed)
  1.1160 -            {
  1.1161 -                LexPushed = false;
  1.1162 -                return _LastToken;
  1.1163 -            }
  1.1164 -
  1.1165 -            /* Number of chars we will be deleting from the input */
  1.1166 -            int stripchars = 0;
  1.1167 -
  1.1168 -            /* Clear our state */
  1.1169 -            _LastToken = LexToken.TOKEN_NONE;
  1.1170 -
  1.1171 -            /* Remove stuff we don't want from the line */
  1.1172 -            preprocess_line();
  1.1173 -
  1.1174 -            if (Contents.Length < 1)
  1.1175 -            {
  1.1176 -                _LastToken = LexToken.TOKEN_EOF;
  1.1177 -                return _LastToken;
  1.1178 -            }
  1.1179 -            
  1.1180 -            /* Get the token list */
  1.1181 -            KeywordToken[] tokens = Tokenizer.Tokens;
  1.1182 -            for (int i = 0; i < tokens.Length; i++)
  1.1183 -            {
  1.1184 -                if (!CheckString(0, tokens[i].keyword))
  1.1185 -                {
  1.1186 -                    continue;
  1.1187 -                }
  1.1188 -                int len = tokens[i].keyword.Length;
  1.1189 -                /* Now check to see what the next token is */
  1.1190 -                if (Contents.Length == len
  1.1191 -                    || IsNotKeywordChar(Contents[len]))
  1.1192 -                {
  1.1193 -                    /* We have a token match! */
  1.1194 -                    _LastToken = tokens[i].token;
  1.1195 -                    _LexString = null;
  1.1196 -                    _LexChar = '\0';
  1.1197 -                    stripchars = len;
  1.1198 -                    break;
  1.1199 -                }
  1.1200 -            }
  1.1201 -
  1.1202 -            if (_LastToken == LexToken.TOKEN_NONE)
  1.1203 -            {
  1.1204 -                /* See if we can try to read a symbol */
  1.1205 -                if (IsSymbolChar(Contents[0], true))
  1.1206 -                {
  1.1207 -                    int characters = 1;
  1.1208 -                    while (Contents[characters] != '\0'
  1.1209 -                           && IsSymbolChar(Contents[characters], false))
  1.1210 -                    {
  1.1211 -                        characters++;
  1.1212 -                    }
  1.1213 -                    stripchars = characters;
  1.1214 -                    /* We're done! See what's next.. */
  1.1215 -                    if (Contents[characters] == ':')
  1.1216 -                    {
  1.1217 -                        _LastToken = LexToken.TOKEN_LABEL;
  1.1218 -                        stripchars++;
  1.1219 -                    }
  1.1220 -                    else
  1.1221 -                    {
  1.1222 -                        _LastToken = LexToken.TOKEN_SYMBOL;
  1.1223 -                    }
  1.1224 -                    _LexString = Contents.ToString().Substring(0, characters);
  1.1225 -                    _LexChar = _LexString[0];
  1.1226 -                }/*
  1.1227 -                else if (Contents[0] == '"')
  1.1228 -                {
  1.1229 -                    bool reached_end = false;
  1.1230 -                    StringBuilder builder = new StringBuilder();
  1.1231 -                    for (int i = 1; i < Contents.Length; i++)
  1.1232 -                    {
  1.1233 -                        if (i < Contents.Length - 1
  1.1234 -                            && Contents[i] == '\\'
  1.1235 -                            && IsEscapedChar(Contents[i+1]))
  1.1236 -                        {
  1.1237 -                            i++;
  1.1238 -                        }
  1.1239 -                        else if (Contents[i] == '"')
  1.1240 -                        {
  1.1241 -                            reached_end = true;
  1.1242 -                            break;
  1.1243 -                        }
  1.1244 -                        builder.Append(Contents[i]);
  1.1245 -                    }
  1.1246 -                    if (!reached_end)
  1.1247 -                    {
  1.1248 -                        throw new ParseException("Expected end of string; none found");
  1.1249 -                    }
  1.1250 -                    _LexString = builder.ToString();
  1.1251 -                    _LexChar = _LexString.Length > 0 ? _LexString[0] : '\0';
  1.1252 -                }*/
  1.1253 -                else if (Contents[0] == '\'')
  1.1254 -                {
  1.1255 -                    char c = '\0';
  1.1256 -                    if (Contents.Length < 3)
  1.1257 -                    {
  1.1258 -                        throw new ParseException("Expected end of character; none found");
  1.1259 -                    }
  1.1260 -                    else if (Contents[1] == '\\')
  1.1261 -                    {
  1.1262 -                        if (Contents.Length < 4 || !IsEscapedChar(Contents[2]))
  1.1263 -                        {
  1.1264 -                            throw new ParseException("Expected end of character; none found");
  1.1265 -                        }
  1.1266 -                        if (Contents[2] == 'r')
  1.1267 -                        {
  1.1268 -                            c = '\r';
  1.1269 -                        }
  1.1270 -                        else if (Contents[2] == 'n')
  1.1271 -                        {
  1.1272 -                            c = '\n';
  1.1273 -                        }
  1.1274 -                        else if (Contents[2] == 't')
  1.1275 -                        {
  1.1276 -                            c = '\t';
  1.1277 -                        }
  1.1278 -                        else if (Contents[2] == 'v')
  1.1279 -                        {
  1.1280 -                            c = '\v';
  1.1281 -                        }
  1.1282 -                        else if (Contents[2] == '\\')
  1.1283 -                        {
  1.1284 -                            c = '\\';
  1.1285 -                        }
  1.1286 -                        else if (Contents[2] == '"')
  1.1287 -                        {
  1.1288 -                            c = '"';
  1.1289 -                        }
  1.1290 -                        stripchars = 4;
  1.1291 -                    }
  1.1292 -                    else
  1.1293 -                    {
  1.1294 -                        c = Contents[1];
  1.1295 -                        stripchars = 3;
  1.1296 -                    }
  1.1297 -                    _LexString = c.ToString();
  1.1298 -                    _LexChar = c;
  1.1299 -                    _LastToken = LexToken.TOKEN_QUOTCHAR;
  1.1300 -                }
  1.1301 -                else if (CheckString(0, "/**"))
  1.1302 -                {
  1.1303 -                    int endpoint = 0;
  1.1304 -                    for (int i=3; i<Contents.Length-1; i++)
  1.1305 -                    {
  1.1306 -                        if (Contents[i] == '\n')
  1.1307 -                        {
  1.1308 -                            LineNo++;
  1.1309 -                        }
  1.1310 -                        else if (Contents[i] == '*' && Contents[i+1] == '/')
  1.1311 -                        {
  1.1312 -                            endpoint = i+1;
  1.1313 -                            break;
  1.1314 -                        }
  1.1315 -                    }
  1.1316 -                    if (endpoint == 0)
  1.1317 -                    {
  1.1318 -                        throw new ParseException("Expected end of multi-line comment; found end of file");
  1.1319 -                    }
  1.1320 -                    /* We have to factor one more character in because we're zero based */
  1.1321 -                    endpoint++;
  1.1322 -                    _LastToken = LexToken.TOKEN_DOCBLOCK;
  1.1323 -                    _LexString = Contents.ToString().Substring(0, endpoint);
  1.1324 -                    _LexChar = _LexString[0];
  1.1325 -                    stripchars = endpoint;
  1.1326 -                }
  1.1327 -                else
  1.1328 -                {
  1.1329 -                    _LastToken = LexToken.TOKEN_CHARACTER;
  1.1330 -                    _LexString = Contents[0].ToString();
  1.1331 -                    _LexChar = Contents[0];
  1.1332 -                    stripchars = 1;
  1.1333 -                }
  1.1334 -            }
  1.1335 -
  1.1336 -            /* Strip N chars */
  1.1337 -            if (stripchars > 0)
  1.1338 -            {
  1.1339 -                Contents.Remove(0, stripchars);
  1.1340 -            }
  1.1341 -
  1.1342 -            return _LastToken;
  1.1343 -        }
  1.1344 -    }
  1.1345 -}