Edit

kc3-lang/angle/src/compiler/preprocessor/new/Input.cpp

Branch :

  • Show log

    Commit

  • Author : alokp@chromium.org
    Date : 2011-08-07 05:36:04
    Hash : 4e4b807d
    Message : Beginnings of a new preprocessor. Review URL: http://codereview.appspot.com/4830050 git-svn-id: https://angleproject.googlecode.com/svn/trunk@718 736b8ea6-26fd-11df-bfd4-992fa37f6226

  • src/compiler/preprocessor/new/Input.cpp
  • //
    // Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    #include "Input.h"
    
    #include <cstdio>
    
    #include "compiler/debug.h"
    
    namespace pp
    {
    
    Input::Input(int count, const char* const string[], const int length[])
        : mCount(count),
          mString(string),
          mLength(length),
          mIndex(-1),
          mSize(0),
          mError(kErrorNone),
          mState(kStateInitial)
    {
        ASSERT(mCount >= 0);
        switchToNextString();
    }
    
    bool Input::eof() const
    {
        ASSERT(mIndex <= mCount);
        return mIndex == mCount;
    }
    
    int Input::read(char* buf, int bufSize)
    {
        int nread = 0;
        int startIndex = mIndex;
        // Keep reading until the buffer is full or the current string is exhausted.
        while ((mIndex == startIndex) && (nread < bufSize))
        {
            int c = getChar();
            if (c == EOF)
            {
                if (mState == kStateBlockComment)
                    mError = kErrorUnexpectedEOF;
                break;
            }
    
            switch (mState)
            {
              case kStateInitial:
                if (c == '/')
                {
                    // Potentially a comment.
                    switch (peekChar())
                    {
                      case '/':
                        getChar();  // Eat '/'.
                        mState = kStateLineComment;
                        break;
                      case '*':
                        getChar();  // Eat '*'.
                        mState = kStateBlockComment;
                        break;
                      default:
                        // Not a comment.
                        buf[nread++] = c;
                        break;
                    }
                } else
                {
                    buf[nread++] = c;
                }
                break;
    
              case kStateLineComment:
                if (c == '\n')
                {
                    buf[nread++] = c;
                    mState = kStateInitial;
                }
                break;
    
              case kStateBlockComment:
                if (c == '*' && (peekChar() == '/'))
                {
                    getChar();   // Eat '/'.
                    buf[nread++] = ' ';  // Replace comment with whitespace.
                    mState = kStateInitial;
                } else if (c == '\n')
                {
                    // Line breaks are never skipped.
                    buf[nread++] = c;
                }
                break;
    
              default:
                ASSERT(false);
                break;
            }
        }
    
        return nread;
    }
    
    int Input::getChar()
    {
        if (eof()) return EOF;
    
        const char* str = mString[mIndex];
        int c = str[mSize++];
    
        // Switch to next string if the current one is fully read.
        int length = stringLength(mIndex);
        // We never read from empty string.
        ASSERT(length != 0);
        if (((length < 0) && (str[mSize] == '\0')) ||
            ((length > 0) && (mSize == length)))
            switchToNextString();
    
        return c;
    }
    
    int Input::peekChar()
    {
        // Save the current read position.
        int index = mIndex;
        int size = mSize;
        int c = getChar();
    
        // Restore read position.
        mIndex = index;
        mSize = size;
        return c;
    }
    
    void Input::switchToNextString()
    {
        ASSERT(mIndex < mCount);
    
        mSize = 0;
        do
        {
            ++mIndex;
        } while (!eof() && isStringEmpty(mIndex));
    }
    
    bool Input::isStringEmpty(int index)
    {
        ASSERT(index < mCount);
    
        const char* str = mString[mIndex];
        int length = stringLength(mIndex);
        return (length == 0) || ((length < 0) && (str[0] == '\0'));
    }
    
    int Input::stringLength(int index)
    {
        ASSERT(index < mCount);
        return mLength ? mLength[index] : -1;
    }
    
    }  // namespace pp