Ejemplo n.º 1
0
class SieveCommand * SieveParser::command()
{
    whitespace();

    SieveCommand * sc = new SieveCommand;
    sc->setParser( this );
    sc->setStart( pos() );

    sc->setIdentifier( identifier() );
    sc->setArguments( arguments() );
    whitespace();
    if ( nextChar() == '{' ) {
        sc->setBlock( block() );
    }
    else if ( present( ";" ) ) {
        // fine
    }
    else {
        setError( "Garbage after command: " + following() );
        // if the line ends with ';', skip ahead to it
        uint x = pos();
        while ( x < input().length() &&
                input()[x] != '\n' && input()[x] != '\r' )
            x++;
        if ( x > pos() && input()[x-1] == ';' )
            step( x - pos() );
    }

    sc->setError( error() );
    sc->setEnd( pos() );
    return sc;
}
Ejemplo n.º 2
0
void SieveScript::parse( const EString & script )
{
    d->source = script;
    SieveParser p( script );
    d->script = p.commands();

    // if we're not yet at the end, treat whatever follows as another
    // command, which will have a nice big error message.
    p.whitespace();
    if ( !p.atEnd() ) {
        SieveCommand * sc = p.command();
        sc->setError( "Junk at end of script" );
        d->script->append( sc );
    }

    // require is only permitted at the start
    List<SieveCommand>::Iterator s( d->script );
    while ( s && s->identifier() == "require" ) {
        s->setRequirePermitted( true );
        ++s;
    }

    // do the semantic bits of parsing
    s = d->script->first();
    EString prev;
    while ( s ) {
        s->setParent( this );
        s->parse( prev );
        prev = s->identifier();
        ++s;
    }

    // check that require lists the right extensions
    EStringList * extensions = p.extensionsNeeded();
    EStringList declared;
    s = d->script->first();
    while ( s && s->identifier() == "require" ) {
        if ( s->error().isEmpty() ) {
            UStringList * r = 0;
            if ( s->arguments() &&
                 s->arguments()->arguments() &&
                 s->arguments()->arguments()->first() )
                r = s->arguments()->arguments()->first()->stringList();
            UStringList::Iterator i( r );
            while ( i ) {
                if ( i->isAscii() )
                    declared.append( i->ascii() );
                ++i;
            }
        }
        ++s;
    }
    declared.append( "comparator-i;octet" );
    declared.append( "comparator-i;ascii-casemap" );
    declared.append( "fileinto" );
    declared.append( "reject" );
    EStringList::Iterator i( extensions );
    EStringList undeclared;
    while ( i ) {
        if ( !declared.contains( *i ) )
            undeclared.append( i->quoted() );
        ++i;
    }
    if ( !undeclared.isEmpty() ) {
        SieveCommand * f = d->script->first();
        if ( f->identifier() == "require" )
            f->setError( "Extensions used but not declared: " +
                         undeclared.join( ", " ) );
        else
            f->setError( "Missing require: require [ " +
                         undeclared.join( ", " ) + " ];" );
    }

    // and find all the errors
    d->errors = p.bad( this );
}