Exemple #1
0
bool FloatParser::judge(const std::string& token)
{
    size_t posE = std::min( token.find('e'), token.find('E'));
    return (posE != token.npos) ? isSimpleFloat(token.substr(0,posE)) && isSimpleInt(token.substr(posE+1)) : isSimpleFloat(token);
}
Exemple #2
0
bool
Lexer::getNextToken(Token *token, Error *error)
{
    error->instance = ErrorInst::Null;

    if (!(ungot_tokens.empty())) {
        Token *popped_token = ungot_tokens.back();
        ungot_tokens.pop_back();
        popped_token->copyTo(token);
        delete(popped_token);
        return true;
    }

    /* Set when a token is hit: will be used for token begin position. */
    int begin_line_count = current.getLineNumber();
    int begin_col_count  = current.getColumnNumber();

    /* Set everytime: will be the last position for the token as well
     * as the current position for the context. */
    int end_line_count = begin_line_count;
    int end_col_count  = begin_col_count;

    /* Current character. */
    int c;

    /* Current token type. */
    int type = TokenType::Null;

    /* Reset token string buffer. */
    token->str_value.clear();
    token->str_value.reserve(20);

    for (;;) {
        c = getchar_();

        if (reset_position) {
            begin_line_count = 1;
            end_line_count   = 1;

            int col_diff     = end_col_count - begin_col_count;
            begin_col_count  = 1;
            end_col_count    = col_diff + 1;

            reset_position = false;
        }

        /* Single-line comments. */
        if ((c == ';') && (token->str_value.compare("#\\"))) {
            if (type) {
                ungetchar_(c);
                break;
            }

            while ((c = getchar_()) && c != EOF && c != '\n') {
            }

            end_line_count++;
            end_col_count = 1;
            begin_col_count = 1;
            continue;
        }

        /* Multiple-line comments */
        if ((c == '|') && !(token->str_value.compare("#"))) {
            type = TokenType::Null;
            int count = 1;
            int last = c;
            while ((c = getchar_()) && (c != EOF)) {
                if (c == '\n') {
                    end_line_count++;
                    end_col_count = 1;
                } else {
                    end_col_count++;
                }
                if ((last == '|') && (c == '#')) {
                    count--;
                } else if ((last == '#') && (c == '|')) {
                    count++;
                }
                if (!count) {
                    break;
                }
                last = c;
            }
            if (c != EOF) {
                getchar_();
            }
            end_col_count = 1;
            begin_col_count = 1;
            token->str_value.clear();
            token->str_value.reserve(20);
            continue;
        }

        /* String literals. */
        if ((c == '"') && (token->str_value.compare("#\\"))) {
            if (type) {
                ungetchar_(c);
                break;
            }
            type = TokenType::StringLiteral;
            begin_line_count = end_line_count;
            begin_col_count  = end_col_count;

            /* Read characters until you hit a double-quote. */
            while ((c = getchar_())
                    && c != EOF
                    && ((c != '"')
                        || (token->str_value.length() &&
                            (token->str_value[
                                 token->str_value.length() - 1
                             ] == '\\')))) {
                if (c == '"') {
                    token->str_value[
                        token->str_value.length() - 1
                    ] = c;
                } else {
                    token->str_value.push_back(c);
                }
                end_col_count++;
            }
            if (c == EOF) {
                error->instance =
                    ErrorInst::UnterminatedStringLiteral;
            } else {
                end_col_count++;
            }
            break;
        }

        /* Whitespace. */
        if (isspace(c)) {
            if (type) {
                ungetchar_(c);
                break;
            }

            if (c == '\n') {
                end_line_count++;
                end_col_count   = 1;
                begin_col_count = 1;
            } else {
                end_col_count++;
            }
            continue;
        }

        /* End-of-file. */
        if (c == EOF) {
            if (type) {
                ungetchar_(c);
                break;
            }

            type = TokenType::Eof;
            break;
        }

        /* Left parenthesis. */
        if (c == '(' && (token->str_value.compare("#\\"))) {
            if (type) {
                ungetchar_(c);
                break;
            }
            type = TokenType::LeftParen;
            begin_line_count = end_line_count;
            begin_col_count  = end_col_count;
            end_col_count++;
            break;
        }

        /* Right parenthesis. */
        if (c == ')' && (token->str_value.compare("#\\"))) {
            if (type) {
                ungetchar_(c);
                break;
            }
            type = TokenType::RightParen;
            begin_line_count = end_line_count;
            begin_col_count  = end_col_count;
            end_col_count++;
            break;
        }

        /* Potential integer. */
        if ((!type) && ((c == '-') || isdigit(c))) {
            type = TokenType::Int;
            begin_col_count  = end_col_count;
            begin_line_count = end_line_count;
        }

        /* Plain token. */
        if (!type) {
            type = TokenType::String;
            begin_col_count  = end_col_count;
            begin_line_count = end_line_count;
        }

        token->str_value.push_back(c);
        end_col_count++;
    }

    token->type = type;

    if (type == TokenType::Int) {
        if ((token->str_value.length() == 1)
                && (token->str_value[0] == '-')) {
            token->type = TokenType::String;
        } else if (strchr(token->str_value.c_str(), '.')) {
            token->type = TokenType::FloatingPoint;
            if (!isSimpleFloat(token->str_value.c_str())) {
                error->instance =
                    ErrorInst::InvalidFloatingPointNumber;
            }
        } else {
            if (!isSimpleInt(token->str_value.c_str())) {
                error->instance = ErrorInst::InvalidInteger;
            }
        }
    }

    current.setLineAndColumn(end_line_count, end_col_count);

    if (error->instance == ErrorInst::Null) {
        token->begin.setLineAndColumn(
            begin_line_count,
            begin_col_count
        );
        current.copyTo(&(token->end));
        return true;
    } else {
        error->begin.setLineAndColumn(
            begin_line_count,
            begin_col_count
        );
        current.copyTo(&(error->end));
        return false;
    }
}