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; }
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 ); }