Exemple #1
0
bool Parser::parseCharacterClassQuantifier(JumpList& failures, const CharacterClass& charClass, bool invert)
{
    Quantifier q = consumeQuantifier();

    switch (q.type) {
    case Quantifier::None: {
        m_generator.generateCharacterClass(failures, charClass, invert);
        break;
    }

    case Quantifier::Greedy: {
        GenerateCharacterClassFunctor functor(&charClass, invert);
        m_generator.generateGreedyQuantifier(failures, functor, q.min, q.max);
        break;
    }

    case Quantifier::NonGreedy: {
        GenerateCharacterClassFunctor functor(&charClass, invert);
        m_generator.generateNonGreedyQuantifier(failures, functor, q.min, q.max);
        break;
    }

    case Quantifier::Error:
        return false;
    }
    
    return true;
}
bool Parser::parseParentheses(JumpList& failures)
{
    ParenthesesType type = consumeParenthesesType();

    // FIXME: WREC originally failed to backtrack correctly in cases such as
    // "c".match(/(.*)c/). Now, most parentheses handling is disabled. For
    // unsupported parentheses, we fall back on PCRE.

    switch (type) {
        case Generator::Assertion: {
            m_generator.generateParenthesesAssertion(failures);

            if (consume() != ')') {
                setError(ParenthesesUnmatched);
                return false;
            }

            Quantifier quantifier = consumeQuantifier();
            if (quantifier.type != Quantifier::None && quantifier.min == 0) {
                setError(ParenthesesNotSupported);
                return false;
            }

            return true;
        }
        case Generator::InvertedAssertion: {
            m_generator.generateParenthesesInvertedAssertion(failures);

            if (consume() != ')') {
                setError(ParenthesesUnmatched);
                return false;
            }

            Quantifier quantifier = consumeQuantifier();
            if (quantifier.type != Quantifier::None && quantifier.min == 0) {
                setError(ParenthesesNotSupported);
                return false;
            }

            return true;
        }
        default:
            setError(ParenthesesNotSupported);
            return false;
    }
}
Exemple #3
0
bool Parser::parseParentheses(JumpList& failures)
{
    ParenthesesType type = consumeParenthesesType();

    // FIXME: WREC originally failed to backtrack correctly in cases such as
    // "c".match(/(.*)c/). Now, most parentheses handling is disabled. For
    // unsupported parentheses, we fall back on PCRE.

    switch (type) {
        case Generator::Assertion:
            m_generator.generateParenthesesAssertion(failures);

            if (consume() != ')') {
                setError(ParenthesesUnmatched);
                return false;
            }
            
            // A quantifier after an assertion is meaningless, since assertions
            // don't move index forward. So, we discard it.
            consumeQuantifier();
            break;

        case Generator::InvertedAssertion:
            m_generator.generateParenthesesInvertedAssertion(failures);

            if (consume() != ')') {
                setError(ParenthesesUnmatched);
                return false;
            }
            
            // A quantifier after an assertion is meaningless, since assertions
            // don't move index forward. So, we discard it.
            consumeQuantifier();
            break;

        default:
            setError(ParenthesesNotSupported);
            return false;
    }

    return true;
}
Exemple #4
0
bool Parser::parseBackreferenceQuantifier(JumpList& failures, unsigned subpatternId)
{
    Quantifier q = consumeQuantifier();

    switch (q.type) {
    case Quantifier::None: {
        m_generator.generateBackreference(failures, subpatternId);
        break;
    }

    case Quantifier::Greedy:
    case Quantifier::NonGreedy:
        m_generator.generateBackreferenceQuantifier(failures, q.type, subpatternId, q.min, q.max);
        return true;

    case Quantifier::Error:
        return false;
    }
    
    return true;
}
Exemple #5
0
void Parser::parseAlternative(JumpList& failures)
{
    PatternCharacterSequence sequence(m_generator, failures);

    while (1) {
        switch (peek()) {
        case EndOfPattern:
        case '|':
        case ')':
            sequence.flush();
            return;

        case '*':
        case '+':
        case '?':
        case '{': {
            Quantifier q = consumeQuantifier();

            if (q.type == Quantifier::None) {
                sequence.append(consume());
                continue;
            }

            if (q.type == Quantifier::Error)
                return;

            if (!sequence.size()) {
                setError(QuantifierWithoutAtom);
                return;
            }

            sequence.flush(q);
            continue;
        }

        case '^':
            consume();

            sequence.flush();
            m_generator.generateAssertionBOL(failures);
            continue;

        case '$':
            consume();

            sequence.flush();
            m_generator.generateAssertionEOL(failures);
            continue;

        case '.':
            consume();

            sequence.flush();
            if (!parseCharacterClassQuantifier(failures, CharacterClass::newline(), true))
                return;
            continue;

        case '[':
            consume();

            sequence.flush();
            if (!parseCharacterClass(failures))
                return;
            continue;

        case '(':
            consume();

            sequence.flush();
            if (!parseParentheses(failures))
                return;
            continue;

        case '\\': {
            consume();

            Escape escape = consumeEscape(false);
            if (escape.type() == Escape::PatternCharacter) {
                sequence.append(PatternCharacterEscape::cast(escape).character());
                continue;
            }

            sequence.flush();
            if (!parseNonCharacterEscape(failures, escape))
                return;
            continue;
        }

        default:
            sequence.append(consume());
            continue;
        }
    }
}