bool CssParser::parseAny (TokenList* tokens) { switch(tokenizer->getTokenType()) { case Token::NUMBER: case Token::PERCENTAGE: case Token::DIMENSION: case Token::STRING: case Token::URL: case Token::HASH: case Token::UNICODE_RANGE: case Token::INCLUDES: case Token::DASHMATCH: case Token::COLON: case Token::OTHER: tokens->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); break; case Token::PAREN_OPEN: tokens->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); skipWhitespace(); while (parseAny(tokens) || parseUnused(tokens)) {} if (tokenizer->getTokenType() != Token::PAREN_CLOSED) { throw new ParseException(tokenizer->getToken()->str, "closing parenthesis (')')"); } tokens->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); break; case Token::IDENTIFIER: tokens->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); break; case Token::BRACE_OPEN: tokens->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); skipWhitespace(); while (parseAny(tokens) || parseUnused(tokens)) {} if (tokenizer->getTokenType() != Token::BRACE_CLOSED) { throw new ParseException(tokenizer->getToken()->str, "closing brace (']')"); } tokens->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); break; default: return false; } parseWhitespace(tokens); return true; }
bool LessParser::parseSelector(Selector &selector) { if (!parseAny(selector)) return false; while (parseAny(selector) || parseSelectorVariable(selector)) {}; // delete trailing whitespace selector.rtrim(); return true; }
bool CssParser::parseSelector(Selector* selector) { if (!parseAny(selector)) return false; while (parseAny(selector)) {}; // delete trailing whitespace while (selector->back()->type == Token::WHITESPACE) { delete selector->pop(); } return true; }
bool CssParser::parseBlock (TokenList* tokens) { if (tokenizer->getTokenType() != Token::BRACKET_OPEN) return false; tokens->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); skipWhitespace(); while (true) { if (!(parseAny(tokens) || parseBlock(tokens))) { if (tokenizer->getTokenType() == Token::ATKEYWORD) { tokens->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); parseWhitespace(tokens); } else if (tokenizer->getTokenType() == Token::DELIMITER) { tokens->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); skipWhitespace(); } else break; } } if (tokenizer->getTokenType() != Token::BRACKET_CLOSED) { throw new ParseException(tokenizer->getToken()->str, "end of block ('}')"); } tokens->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); skipWhitespace(); return true; }
bool LessParser::parseAtRuleOrVariable (LessStylesheet &stylesheet) { Token token; TokenList value, rule; AtRule* atrule = NULL; if (tokenizer->getTokenType() != Token::ATKEYWORD) return false; token = tokenizer->getToken(); tokenizer->readNextToken(); CssParser::skipWhitespace(); #ifdef WITH_LIBGLOG VLOG(2) << "Parse: keyword: " << token; #endif if (parseVariable(value)) { #ifdef WITH_LIBGLOG VLOG(2) << "Parse: variable"; #endif stylesheet.putVariable(token, value); } else { if (token == "@media") { parseLessMediaQuery(token, stylesheet); return true; } while(parseAny(rule)) {}; if (!parseBlock(rule)) { if (tokenizer->getTokenType() != Token::DELIMITER) { throw new ParseException(tokenizer->getToken(), "delimiter (';') at end of @-rule"); } tokenizer->readNextToken(); skipWhitespace(); } // parse import if (token == "@import" && rule.size() > 0) { if (parseImportStatement(rule, stylesheet)) return true; } atrule = stylesheet.createLessAtRule(token); atrule->setReference(reference); atrule->setRule(rule); } return true; }
TokenList* CssParser::parseValue () { TokenList* value = new TokenList(); if (parseAny(value) || parseBlock(value)) { } else if (tokenizer->getTokenType() == Token::ATKEYWORD) { value->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); parseWhitespace(value); } else { delete value; return NULL; } while (true) { if (parseAny(value) || parseBlock(value)) { } else if (tokenizer->getTokenType() == Token::ATKEYWORD) { value->push(tokenizer->getToken()->clone()); tokenizer->readNextToken(); parseWhitespace(value); } else return value; } }
void LessParser::parseLessMediaQuery(Token &mediatoken, LessStylesheet &stylesheet) { LessMediaQuery* query = stylesheet.createLessMediaQuery(); query->setReference(reference); query->getSelector()->push_back(mediatoken); query->getSelector()->push_back(Token::BUILTIN_SPACE); CssParser::skipWhitespace(); while (parseAny(*query->getSelector()) || tokenizer->getTokenType() == Token::ATKEYWORD) { if (tokenizer->getTokenType() == Token::ATKEYWORD) { query->getSelector()->push_back(tokenizer->getToken()); tokenizer->readNextToken(); parseWhitespace(*query->getSelector()); } } #ifdef WITH_LIBGLOG VLOG(2) << "Media query: " << query->getSelector()->toString(); #endif if (tokenizer->getTokenType() != Token::BRACKET_OPEN) { throw new ParseException(tokenizer->getToken(), "{"); } tokenizer->readNextToken(); skipWhitespace(); while (parseStatement(*query)) { skipWhitespace(); } if (tokenizer->getTokenType() != Token::BRACKET_CLOSED) { throw new ParseException(tokenizer->getToken(), "end of media query block ('}')"); } tokenizer->readNextToken(); skipWhitespace(); }
void LessParser::parseMediaQueryRuleset(Token &mediatoken, LessStylesheet &stylesheet, LessRuleset &parent) { MediaQueryRuleset* query = parent.createMediaQuery(); Selector selector; query->setReference(reference); selector.push_back(mediatoken); selector.push_back(Token::BUILTIN_SPACE); CssParser::skipWhitespace(); while (parseAny(selector) || tokenizer->getTokenType() == Token::ATKEYWORD) { if (tokenizer->getTokenType() == Token::ATKEYWORD) { selector.push_back(tokenizer->getToken()); tokenizer->readNextToken(); parseWhitespace(selector); } } query->setSelector(selector); if (tokenizer->getTokenType() != Token::BRACKET_OPEN) { throw new ParseException(tokenizer->getToken(), "{"); } tokenizer->readNextToken(); skipWhitespace(); parseRulesetStatements(stylesheet, *query); if (tokenizer->getTokenType() != Token::BRACKET_CLOSED) { throw new ParseException(tokenizer->getToken(), "end of media query block ('}')"); } tokenizer->readNextToken(); skipWhitespace(); }
AtRule* CssParser::parseAtRule () { AtRule* atrule = NULL; if (tokenizer->getTokenType() != Token::ATKEYWORD) return NULL; atrule = new AtRule(new string(tokenizer->getToken()->str)); tokenizer->readNextToken(); skipWhitespace(); TokenList* rule = new TokenList(); while(parseAny(rule)) {}; if (!parseBlock(rule)) { if (tokenizer->getTokenType() != Token::DELIMITER) { throw new ParseException(tokenizer->getToken()->str, "delimiter (';') at end of @-rule"); } tokenizer->readNextToken(); skipWhitespace(); } atrule->setRule(rule); return atrule; }
bool LessParser::parseAtRuleOrVariable (LessStylesheet &stylesheet) { string keyword, import; TokenList value, rule; AtRule* atrule = NULL; if (tokenizer->getTokenType() != Token::ATKEYWORD) return false; keyword = tokenizer->getToken(); tokenizer->readNextToken(); skipWhitespace(); #ifdef WITH_LIBGLOG VLOG(2) << "Parse: keyword: " << keyword; #endif if (parseVariable(value)) { #ifdef WITH_LIBGLOG VLOG(2) << "Parse: variable"; #endif stylesheet.putVariable(keyword, value); } else { if (keyword == "@media") { parseLessMediaQuery(stylesheet); return true; } while(parseAny(rule)) {}; if (!parseBlock(rule)) { if (tokenizer->getTokenType() != Token::DELIMITER) { throw new ParseException(tokenizer->getToken(), "delimiter (';') at end of @-rule", tokenizer->getLineNumber(), tokenizer->getColumn(), tokenizer->getSource()); } tokenizer->readNextToken(); skipWhitespace(); } // parse import if (keyword == "@import") { if (rule.size() != 1 || rule.front().type != Token::STRING) throw new ParseException(rule.toString(), "A string with the \ file path", tokenizer->getLineNumber(), tokenizer->getColumn(), tokenizer->getSource()); import = rule.front(); #ifdef WITH_LIBGLOG VLOG(2) << "Import filename: " << import; #endif if (import.size() < 5 || import.substr(import.size() - 5, 4) != ".css") { if (import.size() < 6 || import.substr(import.size() - 6, 5) != ".less") import.insert(import.size() - 1, ".less"); importFile(import.substr(1, import.size() - 2), stylesheet); return true; } } atrule = stylesheet.createAtRule(keyword); atrule->setRule(rule); } return true; }