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; }
bool LessParser::parseRuleset (LessStylesheet &stylesheet, Selector &selector, LessRuleset* parent) { LessRuleset* ruleset; if (tokenizer->getTokenType() != Token::BRACKET_OPEN) return false; tokenizer->readNextToken(); skipWhitespace(); #ifdef WITH_LIBGLOG VLOG(2) << "Parse: Ruleset"; #endif // Create the ruleset and parse ruleset statements. if (parent == NULL) ruleset = stylesheet.createLessRuleset(); else ruleset = parent->createNestedRule(); ruleset->setReference(reference); ruleset->setSelector(selector); parseRulesetStatements(stylesheet, *ruleset); if (tokenizer->getTokenType() != Token::BRACKET_CLOSED) { throw new ParseException(tokenizer->getToken(), "end of declaration block ('}')"); } tokenizer->readNextToken(); skipWhitespace(); return true; }
void writeOutput (ostream &out, LessStylesheet &stylesheet, bool format) { Stylesheet css; ProcessingContext context; CssWriter *w1; w1 = format ? new CssPrettyWriter(out) : new CssWriter(out); try{ stylesheet.process(css, context); } catch(ParseException* e) { #ifdef WITH_LIBGLOG LOG(ERROR) << e->getSource() << ": Line " << e->getLineNumber() << ", Column " << e->getColumn() << " Parse Error: " << e->what(); #else cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " << e->getColumn() << " Parse Error: " << e->what(); #endif return; } catch(exception* e) { #ifdef WITH_LIBGLOG LOG(ERROR) << "Error: " << e->what(); #else cerr << "Error: " << e->what(); #endif return; } css.write(*w1); out << endl; delete w1; }
bool LessParser::parseStatement(Stylesheet &stylesheet) { Selector selector; Mixin* mixin; CssComment* comment; LessStylesheet* ls = (LessStylesheet*)&stylesheet; if (tokenizer->getTokenType() == Token::COMMENT) { comment = ls->createComment(); comment->setComment(tokenizer->getToken()); tokenizer->readNextToken(); skipWhitespace(); return true; } else if (parseSelector(selector) && !selector.empty()) { #ifdef WITH_LIBGLOG VLOG(2) << "Parse: Selector: " << selector.toString(); #endif if (parseRuleset(*ls, selector)) return true; // Parameter mixin in the root. Inserts nested rules but no // declarations. mixin = ls->createMixin(); mixin->setReference(reference); if (mixin->parse(selector)) { if (tokenizer->getTokenType() == Token::DELIMITER) { tokenizer->readNextToken(); skipWhitespace(); } return true; } else { ls->deleteMixin(*mixin); throw new ParseException(tokenizer->getToken(), "a declaration block ('{...}') following selector"); } } else { return parseAtRuleOrVariable(*ls); } }
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(); }
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; }