Пример #1
0
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;
}
Пример #2
0
bool LessParser::parseSelector(Selector &selector) {
  if (!parseAny(selector)) 
    return false;
    
  while (parseAny(selector) || parseSelectorVariable(selector)) {};
  
  // delete trailing whitespace
  selector.rtrim();
  return true;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
  }
}
Пример #7
0
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();
}
Пример #8
0
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();
}
Пример #9
0
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;
}
Пример #10
0
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;
}