Пример #1
0
        /** Finds the next nonblank line, skips past an expected preamble, and reads in a string if there is one, and returns it.
         *  Generates an error otherwise. */
        public static string ReadStringWithPreamble(string preamble, IEvolutionState state, StreamReader reader)
        {
            DecodeReturn d = CheckPreamble(preamble, state, reader);

            Decode(d);
            if (d.Type != DecodeReturn.T_STRING)
            {
                state.Output.Fatal("Line " + d.LineNumber +
                                   " has no string after preamble '" + preamble + "'\n-->" + d.Data);
            }
            return(d.S);
        }
Пример #2
0
        /// <summary>
        /// Finds the next nonblank line, then trims the line and checks the preamble.
        /// Returns a DecodeReturn on the line if successful, else posts a fatal error.
        /// Sets the DecodeReturn's line number.  The DecodeReturn has not yet been decoded.
        /// You'll need to do that with Code.Decode(...)
        /// If the "multiline" argument is true, this will append additional lines
        /// up to the first one that is null or empty (blank).
        /// Note that this multiline capability provides the means to reconstitute large blocks of data if needed.
        /// The user must ensure that a blank line (or EOF) marks the end of such blocks.
        /// </summary>
        public static DecodeReturn CheckPreamble(string preamble, IEvolutionState state, StreamReader reader, bool multiline)
        {
            // BRS : TODO : Added Offset because the reader does not provide "linenumber". Check the actual behavior.
            var offset     = reader.BaseStream.Position;
            var linenumber = 0; // throw it away later

            try
            {
                // get non-blank line
                var s = "";
                while (s != null && s.Trim().Equals(""))
                {
                    //linenumber = reader.GetLineNumber();
                    s = reader.ReadLine();
                    linenumber++;
                }

                // check the preamble
                if (s == null || !(s = s.Trim()).StartsWith(preamble))
                {
                    // uh oh
                    state.Output.Fatal("Stream Offset: " + offset + " Line: " + linenumber + " has bad preamble.  Expected '" + preamble + "'. -->" + s);
                }

                // At this point we are exactly the same as the single line version
                if (!multiline)
                {
                    var d = new DecodeReturn(s, preamble.Length)
                    {
                        LineNumber = linenumber
                    };
                    return(d);
                }
                // multiline has been requested...
                var sb = new StringBuilder(s); // Aggregate lines up to the first blank line following the preamble
                while (!String.IsNullOrEmpty(s = reader.ReadLine()))
                {
                    sb = sb.AppendLine(s);
                }
                return(new DecodeReturn(sb.ToString(), preamble.Length)
                {
                    LineNumber = linenumber
                });
            }
            catch (IOException e)
            {
                state.Output.Fatal("On line " + linenumber + "an IO error occurred:\n\n" + e);
                return(null); // never happens
            }
        }
Пример #3
0
        /// <summary>
        /// Decodes the next item out of a DecodeReturn and modifies the DecodeReturn to hold the results.
        /// See DecodeReturn for more explanations about how to interpret the results.
        /// </summary>
        public static void Decode(DecodeReturn d)
        {
            var dat = d.Data;
            var x   = d.Pos;
            var len = d.Data.Length;

            // look for whitespace or ( or )
            for (; x < len; x++)
            {
                if (!Char.IsWhiteSpace(dat[x]) && dat[x] != '(' && dat[x] != ')')
                {
                    break;
                }
            }

            // am I at the end of my rope?
            if (x == len)
            {
                d.Type = DecodeReturn.T_ERROR; d.S = "Out of tokens";
                return;
            }

            // what type am I?
            switch (dat[x])
            {
            case 't':     // boolean (true)
                if (x + 3 < len && dat[x + 1] == 'r' && dat[x + 2] == 'u' && dat[x + 3] == 'e')
                {
                    d.Type = DecodeReturn.T_BOOLEAN;
                    d.B    = true;
                    d.Pos  = x + 4;
                    return;
                }
                else
                {
                    d.Type = DecodeReturn.T_ERROR;
                    d.S    = "Expected a (true) boolean";
                    return;
                }

            case 'T':     // boolean (true)
            {
                d.Type = DecodeReturn.T_BOOLEAN;
                d.B    = true;
                d.Pos  = x + 1;
                return;
            }

            case 'F':     // boolean (false)
            {
                d.Type = DecodeReturn.T_BOOLEAN;
                d.B    = false;
                d.Pos  = x + 1;
                return;
            }

            case 'f':                                                               // float or boolean
                if (len == 1 || Char.IsWhiteSpace(dat[x + 1]) || dat[x + 1] == ')') // Then we must have a lowercase boolean ("false")?
                {
                    d.Type = DecodeReturn.T_BOOLEAN;
                    d.B    = false;
                    d.Pos  = x + 1;
                    return;
                }
                if (x + 4 < len && dat[x + 1] == 'a' && dat[x + 2] == 'l' && dat[x + 3] == 's' && dat[x + 4] == 'e')
                {
                    d.Type = DecodeReturn.T_BOOLEAN; d.B = false; d.Pos = x + 5;
                    return;
                }
                else
                {
                    var    readHuman = false;
                    string sf        = null;
                    var    initial   = x + 1;

                    // look for next '|'
                    for (; x < len; x++)
                    {
                        if (dat[x] == '|')
                        {
                            break;
                        }
                    }

                    if (x == initial)
                    {
                        readHuman = true;
                    }

                    if (x >= len)
                    {
                        d.Type = DecodeReturn.T_ERROR; d.S = "Expected a float";
                        return;
                    }

                    if (!readHuman)
                    {
                        sf = dat.Substring(initial, (x) - (initial));
                    }
                    x++;

                    // look for next '|'
                    var initial2 = x;     // x is now just past first |
                    for (; x < len; x++)
                    {
                        if (dat[x] == '|')
                        {
                            break;
                        }
                    }

                    if (x >= len)
                    {
                        d.Type = DecodeReturn.T_ERROR; d.S = "Expected a float";
                        return;
                    }
                    if (readHuman)
                    {
                        sf = dat.Substring(initial2, (x) - (initial2));
                    }

                    float f;
                    try
                    {
                        if (readHuman)
                        {
                            f = Single.Parse(sf);
                        }
                        else
                        {
                            f = (float)BitConverter.Int64BitsToDouble(Int64.Parse(sf));
                        }
                    }
                    catch (FormatException)
                    {
                        d.Type = DecodeReturn.T_ERROR; d.S = "Expected a float";
                        return;
                    }
                    d.Type = DecodeReturn.T_FLOAT;
                    d.D    = f;
                    d.Pos  = x + 1;
                    return;
                }

            case 'd':      // double
            {
                var    readHuman = false;
                string sf        = null;
                var    initial   = x + 1;

                // look for next '|'
                for (; x < len; x++)
                {
                    if (dat[x] == '|')
                    {
                        break;
                    }
                }

                if (x == initial)
                {
                    readHuman = true;
                }

                if (x >= len)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Expected a double";
                    return;
                }

                if (!readHuman)
                {
                    sf = dat.Substring(initial, (x) - (initial));
                }
                x++;

                // look for next '|'
                var initial2 = x;         // x is now just past first |
                for (; x < len; x++)
                {
                    if (dat[x] == '|')
                    {
                        break;
                    }
                }

                if (x >= len)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Expected a double";
                    return;
                }
                if (readHuman)
                {
                    sf = dat.Substring(initial2, (x) - (initial2));
                }

                double f;
                try
                {
                    if (readHuman)
                    {
                        f = Double.Parse(sf);
                    }
                    else
                    {
                        f = BitConverter.Int64BitsToDouble(Int64.Parse(sf));
                    }
                }
                catch (FormatException)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Expected a double";
                    return;
                }
                d.Type = DecodeReturn.T_DOUBLE;
                d.D    = f;
                d.Pos  = x + 1;
                return;
            }

            case 'b':      // byte
            {
                var initial = x + 1;

                // look for next '|'
                for (; x < len; x++)
                {
                    if (dat[x] == '|')
                    {
                        break;
                    }
                }

                if (x >= len)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Expected a byte";
                    return;
                }
                var sf = dat.Substring(initial, (x) - (initial));

                sbyte f;
                try
                {
                    f = SByte.Parse(sf);
                }
                catch (FormatException)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Expected a byte";
                    return;
                }
                d.Type = DecodeReturn.T_BYTE;
                d.L    = f;
                d.Pos  = x + 1;
                return;
            }

            case 's':      // short
            {
                var initial = x + 1;

                // look for next '|'
                for (; x < len; x++)
                {
                    if (dat[x] == '|')
                    {
                        break;
                    }
                }

                if (x >= len)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Expected a short";
                    return;
                }
                var sf = dat.Substring(initial, (x) - (initial));

                short f;
                try
                {
                    f = Int16.Parse(sf);
                }
                catch (FormatException)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Expected a short";
                    return;
                }
                d.Type = DecodeReturn.T_SHORT;
                d.L    = f;
                d.Pos  = x + 1;
                return;
            }

            case 'i':      // int
            {
                var initial = x + 1;

                // look for next '|'
                for (; x < len; x++)
                {
                    if (dat[x] == '|')
                    {
                        break;
                    }
                }

                if (x >= len)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Expected an int";
                    return;
                }
                var sf = dat.Substring(initial, (x) - (initial));

                int f;
                try
                {
                    f = int.Parse(sf);
                }
                catch (FormatException)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Expected an int";
                    return;
                }
                d.Type = DecodeReturn.T_INT;
                d.L    = f;
                d.Pos  = x + 1;
                return;
            }

            case 'l':      // long
            {
                var initial = x + 1;

                // look for next '|'
                for (; x < len; x++)
                {
                    if (dat[x] == '|')
                    {
                        break;
                    }
                }

                if (x >= len)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Expected a long";
                    return;
                }
                var sf = dat.Substring(initial, (x) - (initial));

                long f;
                try
                {
                    f = Int64.Parse(sf);
                }
                catch (FormatException)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Expected a long";
                    return;
                }
                d.Type = DecodeReturn.T_LONG;
                d.L    = f;
                d.Pos  = x + 1;
                return;
            }

            case '"':      // string
            {
                var sb        = new StringBuilder();
                var inUnicode = false;

                x++;
                for (; x < len; x++)
                {
                    var c = dat[x];
                    if (c == '"')
                    {
                        // done with the string
                        if (inUnicode)
                        // uh oh
                        {
                            d.Type = DecodeReturn.T_ERROR; d.S = "Forgot to terminate Unicode with a '\\u' in the string";
                            return;
                        }
                        d.Type = DecodeReturn.T_STRING;
                        d.S    = sb.ToString();
                        d.Pos  = x + 1;
                        return;
                    }
                    else if (c == '\\')         // escape
                    {
                        x++;
                        if (x >= len)
                        {
                            d.Type = DecodeReturn.T_ERROR; d.S = "Unterminated String";
                            return;
                        }
                        if (dat[x] != 'u' && inUnicode)
                        {
                            d.Type = DecodeReturn.T_ERROR; d.S = "Escape character in Unicode sequence";
                            return;
                        }

                        switch (dat[x])
                        {
                        case 'u':  inUnicode = !inUnicode; break;

                        case 'b':  sb.Append('\b'); break;

                        case 'n':  sb.Append('\n'); break;

                        case '"':  sb.Append('"'); break;

                        case '\'':  sb.Append('\''); break;

                        case 't':  sb.Append('\t'); break;

                        case '\\':  sb.Append('\\'); break;

                        case '0':  sb.Append('\x0000'); break;

                        default:
                        {
                            d.Type = DecodeReturn.T_ERROR; d.S = "Bad escape char in String";
                            return;
                        }
                        }
                    }
                    else if (inUnicode)
                    {
                        if (x + 3 >= len)
                        {
                            d.Type = DecodeReturn.T_ERROR; d.S = "Unterminated String";
                            return;
                        }
                        try
                        {
                            sb.Append((char)(int.Parse("0x" + c + dat[x + 1] + dat[x + 2] + dat[x + 3])));
                            ;
                            x += 3;
                        }
                        catch (System.FormatException)
                        {
                            d.Type = DecodeReturn.T_ERROR; d.S = "Bad Unicode in String";
                            return;
                        }
                    }
                    else
                    {
                        sb.Append(c);
                    }
                }
                d.Type = DecodeReturn.T_ERROR; d.S = "Unterminated String";
                return;
            }

            case '\'':      // char
            {
                x++;
                if (x >= len)
                {
                    d.Type = DecodeReturn.T_ERROR; d.S = "Unterminated char"; return;
                }
                var c = dat[x];
                if (c == '\\')
                {
                    x++;
                    if (x >= len)
                    {
                        d.Type = DecodeReturn.T_ERROR; d.S = "Unterminated char";
                        return;
                    }
                    switch (dat[x])
                    {
                    case 'u':
                        if (x + 4 >= len)
                        {
                            d.Type = DecodeReturn.T_ERROR; d.S = "Unterminated char";
                            return;
                        }
                        try
                        {
                            c = (char)(int.Parse("0x" + dat[x + 1] + dat[x + 2] + dat[x + 3] + dat[x + 4]));
                        }
                        catch (System.FormatException)
                        {
                            d.Type = DecodeReturn.T_ERROR; d.S = "Bad Unicode in char";
                            return;
                        }
                        x += 5;
                        break;

                    case 'b':  c = '\b'; x++; break;

                    case 'n':  c = '\n'; x++; break;

                    case '"':  c = '"'; x++; break;

                    case '\'':  c = '\''; x++; break;

                    case 't':  c = '\t'; x++; break;

                    case '\\':  c = '\\'; x++; break;

                    case '0':  c = '\x0000'; x++; break;

                    default:
                    {
                        d.Type = DecodeReturn.T_ERROR; d.S = "Bad escape char in char";
                        return;
                    }
                    }
                    if (dat[x] != '\'')
                    {
                        d.Type = DecodeReturn.T_ERROR; d.S = "Bad char";
                        return;
                    }
                    d.Type = DecodeReturn.T_CHAR;
                    d.C    = c;
                    d.Pos  = x + 1;
                    return;
                }
                else
                {
                    x++;
                    if (x >= len)
                    {
                        d.Type = DecodeReturn.T_ERROR; d.S = "Unterminated char";
                        return;
                    }
                    if (dat[x] != '\'')
                    {
                        d.Type = DecodeReturn.T_ERROR; d.S = "Bad char";
                        return;
                    }
                    d.Type = DecodeReturn.T_CHAR;
                    d.C    = c;
                    d.Pos  = x + 1;
                    return;
                }
            }

            default:
                d.Type = DecodeReturn.T_ERROR; d.S = "Unknown token";
                return;
            }
        }