Exemplo n.º 1
0
        }         // AddString

        // If the current position of the TextReaderBuffer matches any
        // of our registered strings, then set length to the length of the
        // longest such string, set info to the value supplied in AddString,
        // and return true.  Otherwise leave length and info undefined, and
        // return false.
        public bool Match(TextReaderBuffer reader, out int length, out int info)
        {
            // We don't really need to assign length and info here, but we do so
            // so that the compiler won't complain on any of the "return false"
            // paths.
            length = 0;
            info   = 0;

            char[] buffer;
            int    bufStart;
            int    bufLen = reader.GetBuffer(maxLen, out buffer, out bufStart);

            if (bufLen <= 0)
            {
                return(false);
            }

            // NOTE (snewman 7/12/01): this is currently implemented as a
            // simple linear search over all registered strings, after
            // discriminating by the initial character.  Many more efficient
            // algorithms are possible, such as binary search or tries.  Doesn't
            // seem worthwhile.
            int initialChar = buffer[bufStart];

            bufStart++;
            bufLen--;

            if (initialChar >= strings.Length)
            {
                return(false);
            }

            for (StringEntry candidate = strings[initialChar];
                 candidate != null; candidate = candidate.next)
            {
                if (bufLen >= candidate.headlessString.Length &&
                    MatchChars(buffer, bufStart, candidate.headlessString))
                {
                    if (!candidate.isIdentifier ||
                        bufLen == candidate.headlessString.Length ||
                        !CharUtils.IsIdentifierChar(buffer[bufStart + candidate.headlessString.Length]))
                    {
                        length = candidate.headlessString.Length + 1;
                        info   = candidate.info;
                        return(true);
                    }
                }
            }

            return(false);
        }         // Match
Exemplo n.º 2
0
        }         // ParseStringLiteral

        // Advance the stream past a comment beginning at the current stream
        // location.
        private void SkipComment(SrcLoc loc)
        {
            // HACK SN 7/13/01: rewrite this to support comments longer
            // than maxTokenLen.

            // Get a buffer from which we can parse the comment.
            char[] charBuf;
            int    startPos;
            int    bufLen = buffer.GetBuffer(maxTokenLen, out charBuf,
                                             out startPos);

            int tokenLen = 2;

            if (charBuf[startPos + 1] == '/')
            {
                // C++ style comment; search for end of line
                while (tokenLen < bufLen &&
                       !CharUtils.IsEOLChar(charBuf[startPos + tokenLen]))
                {
                    tokenLen++;
                }
            }
            else
            {
                // C style comment; search for "*/"
                // NOTE: we might extend this to warn for nested comments.
                while (tokenLen < bufLen - 1 &&
                       (charBuf[startPos + tokenLen] != '*' ||
                        charBuf[startPos + tokenLen + 1] != '/'))
                {
                    tokenLen++;
                }

                if (tokenLen >= bufLen - 1)
                {
                    loc.len = tokenLen;
                    throw new ParseError("unterminated /* comment", loc);
                }

                // Include the trailing "*/" in tokenLen.
                tokenLen += 2;
            }

            buffer.Skip(tokenLen);
        }         // SkipComment
Exemplo n.º 3
0
        }         // SkipComment

        // Advance the stream past a block of whitespace beginning at the
        // current stream location.
        //
        // NOTE: the current implementation of this method will only skip
        // up to one buffer's worth of whitespace.  This simplifies the
        // implementation, and is OK because we'll just skip any remaining
        // whitespace in the next go-around of the tokenizer loop.
        private void SkipWhitespace()
        {
            // Get a buffer from which we can search for whitespace.
            char[] charBuf;
            int    startPos;
            int    bufLen = buffer.GetBuffer(maxTokenLen, out charBuf,
                                             out startPos);

            int tokenLen = 1;

            while (tokenLen < bufLen &&
                   CharUtils.IsWhitespaceChar(charBuf[startPos + tokenLen]))
            {
                tokenLen++;
            }

            buffer.Skip(tokenLen);
        }         // SkipWhitespace
Exemplo n.º 4
0
        }         // ParseIdentifier

        // Parse a numeric literal beginning at the current stream location.
        private Token ParseNumber(SrcLoc loc)
        {
            // Get a buffer from which we can parse the number.
            char[] charBuf;
            int    startPos;
            int    bufLen = buffer.GetBuffer(maxTokenLen, out charBuf,
                                             out startPos);

            if (bufLen > maxTokenLen)
            {
                bufLen = maxTokenLen;
            }

            // Find the end of the number.  We match for the following
            // components:
            //
            //    integer part (1 or more digits)
            //    optional fractional part ('.' plus one or more digits)
            //    optional exponent ('E' or 'e', optional '+' or '-', and 1-3 digits)
            //
            // HACK SN 7/14/01: for now, we aren't enforcing that the fractional
            // part must have at least one digit, or that the exponent must have
            // at least 1 and no more than 3 digits.  Review the ECMAScript spec for
            // the correct rules.  Also, should we allow numbers that begin with a '.'
            // (no integer part)?

            int tokenLen = 0;

            while (tokenLen < bufLen &&
                   CharUtils.IsDigitChar(charBuf[startPos + tokenLen]))
            {
                tokenLen++;
            }

            if (tokenLen < bufLen && charBuf[startPos + tokenLen] == '.')
            {
                tokenLen++;
                while (tokenLen < bufLen &&
                       CharUtils.IsDigitChar(charBuf[startPos + tokenLen]))
                {
                    tokenLen++;
                }
            }

            if (tokenLen < bufLen &&
                (charBuf[startPos + tokenLen] == 'E' ||
                 charBuf[startPos + tokenLen] == 'e'))
            {
                tokenLen++;
                if (tokenLen < bufLen &&
                    (charBuf[startPos + tokenLen] == '+' ||
                     charBuf[startPos + tokenLen] == '-'))
                {
                    tokenLen++;
                }

                while (tokenLen < bufLen &&
                       CharUtils.IsDigitChar(charBuf[startPos + tokenLen]))
                {
                    tokenLen++;
                }
            }

            NumLit token = new NumLit();

            token.rawText = buffer.ConsumeString(tokenLen);
            loc.len       = tokenLen;
            token.loc     = loc;

            try
            {
                token.value = Double.Parse(token.rawText);
            }
            catch (FormatException e)
            {
                throw new ParseError("FormatException parsing numeric literal \"" +
                                     token.rawText + "\": " + e.ToString(),
                                     loc);
            }
            catch (OverflowException e)
            {
                throw new ParseError("OverflowException parsing numeric literal \"" +
                                     token.rawText + "\": " + e.ToString(),
                                     loc);
            }

            return(token);
        }         // ParseNumber