Changeset View
Changeset View
Standalone View
Standalone View
libksieve/parser/parser.cpp
Show First 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | return token() == Lexer::QuotedString || | ||||
token() == Lexer::MultiLineString ; | token() == Lexer::MultiLineString ; | ||||
} | } | ||||
bool Parser::Impl::isArgumentToken() const { | bool Parser::Impl::isArgumentToken() const { | ||||
return isStringToken() || | return isStringToken() || | ||||
token() == Lexer::Number || | token() == Lexer::Number || | ||||
token() == Lexer::Tag || | token() == Lexer::Tag || | ||||
( token() == Lexer::Special && mTokenValue == "[" ); | ( token() == Lexer::Special && mTokenValue == QLatin1String("[")) ; | ||||
} | } | ||||
bool Parser::Impl::obtainToken() { | bool Parser::Impl::obtainToken() { | ||||
while ( !mToken && !lexer.atEnd() && !lexer.error() ) { | while ( !mToken && !lexer.atEnd() && !lexer.error() ) { | ||||
mToken = lexer.nextToken( mTokenValue ); | mToken = lexer.nextToken( mTokenValue ); | ||||
if ( lexer.error() ) | if ( lexer.error() ) | ||||
break; | break; | ||||
// comments and line feeds are semantically invisible and may | // comments and line feeds are semantically invisible and may | ||||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | bool Parser::Impl::parseCommand() { | ||||
if ( !obtainToken() ) | if ( !obtainToken() ) | ||||
return false; | return false; | ||||
if ( atEnd() ) { | if ( atEnd() ) { | ||||
makeError( Error::MissingSemicolonOrBlock ); | makeError( Error::MissingSemicolonOrBlock ); | ||||
return false; | return false; | ||||
} | } | ||||
if ( token() == Lexer::Special && tokenValue() == "(" ) { // test-list | if ( token() == Lexer::Special && tokenValue() == QLatin1String ("(")) { // test-list | ||||
if ( !parseTestList() ) { | if ( !parseTestList() ) { | ||||
assert( error() ); | assert( error() ); | ||||
return false; | return false; | ||||
} | } | ||||
} else if ( token() == Lexer::Identifier ) { // should be test: | } else if ( token() == Lexer::Identifier ) { // should be test: | ||||
if ( !parseTest() ) { | if ( !parseTest() ) { | ||||
assert( error() ); | assert( error() ); | ||||
return false; | return false; | ||||
Show All 12 Lines | if ( atEnd() ) { | ||||
return false; | return false; | ||||
} | } | ||||
if ( token() != Lexer::Special ) { | if ( token() != Lexer::Special ) { | ||||
makeUnexpectedTokenError( Error::ExpectedBlockOrSemicolon ); | makeUnexpectedTokenError( Error::ExpectedBlockOrSemicolon ); | ||||
return false; | return false; | ||||
} | } | ||||
if ( tokenValue() == ";" ) | if ( tokenValue() == QLatin1String (";")) | ||||
consumeToken(); | consumeToken(); | ||||
else if ( tokenValue() == "{" ) { // block | else if ( tokenValue() == QLatin1String ("{")) { // block | ||||
if ( !parseBlock() ) | if ( !parseBlock() ) | ||||
return false; // it's an error since we saw '{' | return false; // it's an error since we saw '{' | ||||
} else { | } else { | ||||
makeError( Error::MissingSemicolonOrBlock ); | makeError( Error::MissingSemicolonOrBlock ); | ||||
return false; | return false; | ||||
} | } | ||||
if ( scriptBuilder() ) | if ( scriptBuilder() ) | ||||
Show All 35 Lines | if ( token() == Lexer::Number ) { | ||||
scriptBuilder()->taggedArgument( tokenValue() ); | scriptBuilder()->taggedArgument( tokenValue() ); | ||||
consumeToken(); | consumeToken(); | ||||
return true; | return true; | ||||
} else if ( isStringToken() ) { | } else if ( isStringToken() ) { | ||||
if ( scriptBuilder() ) | if ( scriptBuilder() ) | ||||
scriptBuilder()->stringArgument( tokenValue(), token() == Lexer::MultiLineString, QString() ); | scriptBuilder()->stringArgument( tokenValue(), token() == Lexer::MultiLineString, QString() ); | ||||
consumeToken(); | consumeToken(); | ||||
return true; | return true; | ||||
} else if ( token() == Lexer::Special && tokenValue() == "[" ) { | } else if ( token() == Lexer::Special && tokenValue() == QLatin1String("[")) { | ||||
if ( !parseStringList() ) { | if ( !parseStringList() ) { | ||||
assert( error() ); | assert( error() ); | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
bool Parser::Impl::parseTestList() { | bool Parser::Impl::parseTestList() { | ||||
// test-list := "(" test *("," test) ")" | // test-list := "(" test *("," test) ")" | ||||
if ( !obtainToken() || atEnd() ) | if ( !obtainToken() || atEnd() ) | ||||
return false; | return false; | ||||
if ( token() != Lexer::Special || tokenValue() != "(" ) | if ( token() != Lexer::Special || tokenValue() != QLatin1String("(")) | ||||
return false; | return false; | ||||
if ( scriptBuilder() ) | if ( scriptBuilder() ) | ||||
scriptBuilder()->testListStart(); | scriptBuilder()->testListStart(); | ||||
consumeToken(); | consumeToken(); | ||||
// generic while/switch construct for comma-separated lists. See | // generic while/switch construct for comma-separated lists. See | ||||
// parseStringList() for another one. Any fix here is like to apply there, too. | // parseStringList() for another one. Any fix here is like to apply there, too. | ||||
bool lastWasComma = true; | bool lastWasComma = true; | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | bool Parser::Impl::parseTest() { | ||||
// | // | ||||
if ( !obtainToken() ) | if ( !obtainToken() ) | ||||
return false; | return false; | ||||
if ( atEnd() ) // a test w/o nested tests | if ( atEnd() ) // a test w/o nested tests | ||||
goto TestEnd; | goto TestEnd; | ||||
if ( token() == Lexer::Special && tokenValue() == "(" ) { // test-list | if ( token() == Lexer::Special && tokenValue() == QLatin1String("(")) { // test-list | ||||
if ( !parseTestList() ) { | if ( !parseTestList() ) { | ||||
assert( error() ); | assert( error() ); | ||||
return false; | return false; | ||||
} | } | ||||
} else if ( token() == Lexer::Identifier ) { // should be test: | } else if ( token() == Lexer::Identifier ) { // should be test: | ||||
if ( !parseTest() ) { | if ( !parseTest() ) { | ||||
assert( error() ); | assert( error() ); | ||||
return false; | return false; | ||||
Show All 9 Lines | |||||
bool Parser::Impl::parseBlock() { | bool Parser::Impl::parseBlock() { | ||||
// our ABNF: | // our ABNF: | ||||
// block := "{" [ command-list ] "}" | // block := "{" [ command-list ] "}" | ||||
if ( !obtainToken() || atEnd() ) | if ( !obtainToken() || atEnd() ) | ||||
return false; | return false; | ||||
if ( token() != Lexer::Special || tokenValue() != "{" ) | if ( token() != Lexer::Special || tokenValue() != QLatin1String("{")) | ||||
return false; | return false; | ||||
if ( scriptBuilder() ) | if ( scriptBuilder() ) | ||||
scriptBuilder()->blockStart(); | scriptBuilder()->blockStart(); | ||||
consumeToken(); | consumeToken(); | ||||
if ( !obtainToken() ) | if ( !obtainToken() ) | ||||
return false; | return false; | ||||
Show All 12 Lines | bool Parser::Impl::parseBlock() { | ||||
if ( !obtainToken() ) | if ( !obtainToken() ) | ||||
return false; | return false; | ||||
if ( atEnd() ) { | if ( atEnd() ) { | ||||
makeError( Error::PrematureEndOfBlock ); | makeError( Error::PrematureEndOfBlock ); | ||||
return false; | return false; | ||||
} | } | ||||
if ( token() != Lexer::Special || tokenValue() != "}" ) { | if ( token() != Lexer::Special || tokenValue() != QLatin1String("}")) { | ||||
makeError( Error::NonCommandInCommandList ); | makeError( Error::NonCommandInCommandList ); | ||||
return false; | return false; | ||||
} | } | ||||
if ( scriptBuilder() ) | if ( scriptBuilder() ) | ||||
scriptBuilder()->blockEnd(); | scriptBuilder()->blockEnd(); | ||||
consumeToken(); | consumeToken(); | ||||
return true; | return true; | ||||
} | } | ||||
bool Parser::Impl::parseStringList() { | bool Parser::Impl::parseStringList() { | ||||
// string-list := "[" string *("," string) "]" / string | // string-list := "[" string *("," string) "]" / string | ||||
// ;; if there is only a single string, the brackets are optional | // ;; if there is only a single string, the brackets are optional | ||||
// | // | ||||
// However, since strings are already handled separately from | // However, since strings are already handled separately from | ||||
// string lists in parseArgument(), our ABNF is modified to: | // string lists in parseArgument(), our ABNF is modified to: | ||||
// string-list := "[" string *("," string) "]" | // string-list := "[" string *("," string) "]" | ||||
if ( !obtainToken() || atEnd() ) | if ( !obtainToken() || atEnd() ) | ||||
return false; | return false; | ||||
if ( token() != Lexer::Special || tokenValue() != "[" ) | if ( token() != Lexer::Special || tokenValue() != QLatin1String("[") ) | ||||
return false; | return false; | ||||
if ( scriptBuilder() ) | if ( scriptBuilder() ) | ||||
scriptBuilder()->stringListArgumentStart(); | scriptBuilder()->stringListArgumentStart(); | ||||
consumeToken(); | consumeToken(); | ||||
// generic while/switch construct for comma-separated lists. See | // generic while/switch construct for comma-separated lists. See | ||||
// parseTestList() for another one. Any fix here is like to apply there, too. | // parseTestList() for another one. Any fix here is like to apply there, too. | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | bool Parser::Impl::parseNumber() { | ||||
if ( token() != Lexer::Number ) | if ( token() != Lexer::Number ) | ||||
return false; | return false; | ||||
// number: | // number: | ||||
unsigned long result = 0; | unsigned long result = 0; | ||||
int i = 0; | int i = 0; | ||||
const QByteArray s = tokenValue().toLatin1(); | const QByteArray s = tokenValue().toLatin1(); | ||||
for ( const int len = s.length() ; i < len && isdigit( s[i] ) ; ++i ) { | for ( const int len = s.length() ; i < len && isdigit( s[i] ) ; ++i ) { | ||||
const unsigned long digitValue = s[i] - '0' ; | const unsigned long digitValue = s[i] - QLatin1Char('0').toLatin1() ; | ||||
if ( willOverflowULong( result, digitValue ) ) { | if ( willOverflowULong( result, digitValue ) ) { | ||||
makeError( Error::NumberOutOfRange ); | makeError( Error::NumberOutOfRange ); | ||||
return false; | return false; | ||||
} else { | } else { | ||||
result *= 10 ; result += digitValue ; | result *= 10 ; result += digitValue ; | ||||
} | } | ||||
} | } | ||||
Show All 20 Lines |