bool LessParser::parsePropertyVariable(Selector &selector) { Token variable = tokenizer->getToken(); if (tokenizer->getTokenType() != Token::OTHER || variable != "@") return false; if (tokenizer->readNextToken() != Token::BRACKET_OPEN) throw new ParseException(tokenizer->getToken(), "Opening bracket following @"); variable.append(tokenizer->getToken()); if (tokenizer->readNextToken() != Token::IDENTIFIER) throw new ParseException(tokenizer->getToken(), "Variable inside selector (e.g.: \ @{identifier})"); variable.append(tokenizer->getToken()); if (tokenizer->readNextToken() != Token::BRACKET_CLOSED) throw new ParseException(tokenizer->getToken(), "Closing bracket after variable."); variable.append(tokenizer->getToken()); tokenizer->readNextToken(); selector.push_back(variable); parseWhitespace(selector); 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; }
UnprocessedStatement* LessParser::parseRulesetStatement (LessRuleset &ruleset) { UnprocessedStatement* statement; Selector tokens; size_t property_i; while (parseProperty(tokens) || parsePropertyVariable(tokens)) {} property_i = tokens.size(); parseWhitespace(tokens); parseSelector(tokens); tokens.trim(); if (tokens.empty()) return NULL; statement = ruleset.createUnprocessedStatement(); statement->getTokens()->swap(tokens); statement->property_i = property_i; if (tokenizer->getTokenType() == Token::BRACKET_OPEN) return statement; parseValue(*statement->getTokens()); if (tokenizer->getTokenType() == Token::DELIMITER) { tokenizer->readNextToken(); skipWhitespace(); } return statement; }
bool LessParser::parseSelectorVariable(Selector &selector) { Token* back; if (tokenizer->getTokenType() == Token::BRACKET_OPEN) { back = &selector.back(); if (back->at(back->length() - 1) == '@') { back->append(tokenizer->getToken()); if (tokenizer->readNextToken() != Token::IDENTIFIER) throw new ParseException(tokenizer->getToken(), "Variable inside selector (e.g.: \ @{identifier})"); back->append(tokenizer->getToken()); if (tokenizer->readNextToken() != Token::BRACKET_CLOSED) throw new ParseException(tokenizer->getToken(), "Closing bracket after variable."); back->append(tokenizer->getToken()); tokenizer->readNextToken(); parseWhitespace(selector); return true; } } return false; }
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; }
/////////////////////////////////////////////////////////////////////////// // // Parsing Interface // Token *tokenizer_next( Tokenizer *tokenizer ) { wchar_t c, next; Token *token = NULL; next = ss_peek( tokenizer->ss_ ); while ( next != WEOF && !token ) { // Whitespace if ( isWhitespaceStart( tokenizer->ss_, 0 ) ) { token = parseWhitespace( tokenizer ); } // Strings else if ( isStringStart( tokenizer->ss_, 0 ) ) { token = parseString( tokenizer ); } // Comments else if ( isCommentStart( tokenizer->ss_, 0 ) ) { token = parseComment( tokenizer ); } // URL else if ( isUrlStart( tokenizer->ss_, 0 ) ) { token = parseUrl( tokenizer ); } // SGML Comments else if ( isSGMLCommentStart( tokenizer->ss_, 0 ) ) { token = parseSGMLComment( tokenizer ); } // Identifier else if ( isIdentifierStart( tokenizer->ss_, 0 ) ) { token = parseIdentifier( tokenizer ); } // @keyword else if ( isAtkeywordStart( tokenizer->ss_, 0 ) ) { token = parseAtkeyword( tokenizer ); } // #keyword else if ( isHashkeywordStart( tokenizer->ss_, 0 ) ) { token = parseHashkeyword( tokenizer ); } // Number else if ( isNumberStart( tokenizer->ss_, 0 ) ) { token = parseNumber( tokenizer ); } // Operators & Delims (everything else) else { token = parseEverythingElse( tokenizer ); } } if ( token ) { return token; } else { return NULL; } }
bool Parser::parseMisc( Node *node ) { if( parseWhitespace() ) return true; if( parseComment() ) return true; if( parseProcessingInstruction( node ) ) return true; return false; }
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; } }
bool CssParser::parseUnused(TokenList* tokens) { if (parseBlock(tokens)) { } else 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 return false; return true; }
bool Parser::parseProcessingInstruction (Node * node) { // Processing instructions start with <? if (!doesStreamMatchString ("<?")) return false; std::string name; if (!parseName (name)) reportError ("Valid processing instructions have to have a name."); if (name == "xml") reportError ("Processing instructions cannot have the reserved name 'xml'"); Node *thisNode = new Node; thisNode->setName (name); thisNode->setNodeType (ProcessingInstruction); try { parseWhitespace (); std::string chars; while (!doesStreamMatchString ("?>")) { readChar (false); data += current; // We're in the middle of parsing a processing instruction if (endOfData ()) reportError ("Unterminated processing instruction!"); } thisNode->setData (data); } catch (...) { delete thisNode; throw; } node->addNode (thisNode); return true; }
void Preprocessor::parse(const char* name, const char* text) { if (std::find(names.begin(), names.end(), name) != names.end()) return; files.push_back(File(name, text)); names.push_back(name); list += format("( file %u: %s )\n", (uint) names.size(), name); output.reserve(output.size() + std::strlen(text)); appendToOutput(format("#line 0 %u /* entering %s */\n", (uint) files.size(), files.back().name).c_str()); while (hasMore()) { if (isMultiLineComment()) parseMultiLineComment(); else if (isSingleLineComment()) parseSingleLineComment(); else if (isNewLine()) parseNewLine(); else if (isWhitespace()) parseWhitespace(); else if (isCommand()) parseCommand(); else { advance(1); appendToOutput(); setFirstOnLine(false); } } files.pop_back(); if (!files.empty()) { appendToOutput(format("\n#line %u %u /* returning to %s */", files.back().line, (uint) files.size(), files.back().name).c_str()); } }
Value load(std::istream& ss) { // Parse a JSON entity, using the inputstream ss parseWhitespace(ss); switch (ss.peek()) { case '{': return parseObject(ss); case '[': return parseArray(ss); case '"': return parseString(ss); case 't': return parseTrue(ss); case 'f': return parseFalse(ss); case 'n': return parseNull(ss); case '-': return parseNumber(ss); default: if(isdigit(ss.peek())) { return parseNumber(ss); } else { throw ParseError(std::string("unexpected token: '")+char(ss.peek())+"'"); } } }
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(); }
bool Parser::parseETag( Node *node ) { if( !doesStreamMatchString( "</" ) ) return false; std::string name; if( !parseName( name ) ) return false; if( name != node->name() ) reportError( "End tag name '" + name + "' does not match start tag name '" + node->name() + "'" ); parseWhitespace(); if( current != '>' ) reportError( "End tag missing: '>'" ); readChar(); // Skip to the next char return true; }
void Parser::parse(list<Token> tokens) { for (list<Token>::iterator it=tokens.begin(); it != tokens.end(); it++) { token = *it; TokenType type = token.getType(); if (comment && type != LINE_END) continue; switch(type) { case SEMICOLON: parseSemicolon(); break; case LINE_START: parseLineStart(); break; case LINE_END: parseLineEnd(); break; case COLON: parseColon(); break; case WHITESPACE: parseWhitespace(); break; case COMMA: parseComma(); break; case TEXT: parseText(); break; } } }
bool Parser::parseElement( Node *node ) { if( current != '<' ) return false; State state = SaveState(); std::string name; readChar( false ); if( !parseName( name ) ) { RestoreState( state ); return false; } Node *thisNode = new Node; thisNode->setName( name ); thisNode->setNodeType( Element ); try { do { parseWhitespace(); } while( parseAttribute( thisNode ) ); // Empty Element Tag if( current == '/' ) { readChar( false ); if( current != '>' ) reportError( "Tag not terminated properly." ); readChar(); // Skip Char } // Normal Start Tag else if( current == '>' ) { readChar( false ); parseContent( thisNode ); //thisNode->setData( thisNode->data().replace( ... ) ); // was: ThisNode.Data := TrimChars(ThisNode.Data, [' ', #9, #13, #10]); if( !parseETag( thisNode ) ) reportError( "No ending tag for " + name ); } // Not terminated properly else { reportError( "Tag not terminated properly." ); } } catch( ... ) { delete thisNode; throw; } node->addNode( thisNode ); return true; }
/** Parses a character. */ bool parse(char c) { parseWhitespace(); return !isEnd() && *m_it == c ? ++m_it, true : false; }