/** True if the next token begins the close tag */ static bool atClose(TextInput& t, const std::string name) { if ((t.peek().type() == Token::SYMBOL) && (t.peek().string() == "<")) { // Need to keep looking ahead Token p0 = t.read(); if ((t.peek().type() == Token::SYMBOL) && (t.peek().string() == "/")) { // Check the name on the close tag. It *must* match if // this is a well-formed document, but there might be a // tag error. Token p1 = t.read(); Token p2 = t.peek(); std::string s = p2.string(); debugAssertM(beginsWith(name, s), "Mismatched close tag"); // Put the tokens back t.push(p1); t.push(p0); return true; } else { // Put the read token back t.push(p0); return false; } } else { return false; } }
bool GPUProgram::BindingTable::consumeSymbol(TextInput& ti, const std::string& s) { Token t = ti.peek(); if (symbolMatch(t, s)) { ti.readSymbol(s); return true; } else { return false; } }
GLenum Shader::ShaderProgram::getDeclarationType(TextInput& ti, bool& uniform) { uniform = false; if (ti.peek().type() == Token::SYMBOL) { bool readyForType = false; String s = ti.peek().string(); //Parse all qualifiers before the type: while (! readyForType) { if (isQualifier(s)) { uniform = (uniform || (s == "uniform")); ti.readSymbol(s); s = ti.peek().string(); } else if (s == "layout") { //This should properly parse through all possible layout inputs //http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf (pg52) ti.readSymbol(s); ti.readSymbol("("); Token t = ti.read(); while ((t.type() != Token::SYMBOL) || (t.string() != ")")) { t = ti.read(); } s = ti.peek().string(); } else { // The next token is not a qualifier of any sort, so it is probably the type, if this is a declaration readyForType = true; } } // Read the type String variableSymbol = ti.readSymbol(); // check for unsigned int, short, long long, etc if (variableSymbol == "unsigned") { while (toGLType(variableSymbol + " " + ti.peek().string()) != GL_NONE) { variableSymbol += " " + ti.readSymbol(); } } // If the variableSymbol is not a valid type, then this is not a variable declaration, and GL_NONE will be returned // Checking for not being a declaration cannot be done earlier, as a declaration could have no qualifiers return toGLType(variableSymbol); } else { return GL_NONE; } }
void GPUProgram::BindingTable::parseConstant(TextInput& ti) { if (consumeSymbol(ti, "c") && consumeSymbol(ti, "[")) { // constant Token t = ti.peek(); if (t.type() == Token::NUMBER) { Binding binding; binding.source = CONSTANT; binding.type = FLOAT4; binding.slot = iRound(ti.readNumber()); if (consumeSymbol(ti, "]") && consumeSymbol(ti, "=")) { for (int i = 0; i < 4; ++i) { t = ti.peek(); if (t.type() == Token::NUMBER) { binding.vector[i] = ti.readNumber(); } } bindingArray.append(binding); } } } }
void XML::deserialize(TextInput& t) { begin: Token n = t.read(); m_attribute.clear(); m_child.clear(); m_name = ""; m_value = ""; if ((n.type() == Token::SYMBOL) && (n.string() == "<")) { // Beginning a tag // Read name n = t.read(); debugAssert(n.type() == Token::SYMBOL); bool isComment = (n.string() == "!") && (t.peek().type() == Token::SYMBOL) && (t.peek().string() == "--"); // ignored tag: <?xml> or <!xml> // comment tag: <!-- ... --> if ((n.string() == "?") || ((n.string() == "!") && ! isComment)) { // Ignore this tag while (t.hasMore() && ! ((n.type() == Token::SYMBOL) && (n.string() == ">"))) { n = t.read(); } goto begin; } else if (isComment) { // Ignore until "-->" bool prevWasDash = false; while (t.hasMore() && ! ((n.type() == Token::SYMBOL) && (n.string() == ">") && prevWasDash)) { prevWasDash = (n.type() == Token::SYMBOL) && (n.string() == "--"); n = t.read(); } goto begin; } // Keep reading until no colon m_name += n.string(); n = t.read(); while ((n.type() == Token::SYMBOL) && (n.string() == ":")) { // tag with namespace: <x:y> m_name += ":" + t.readSymbol(); n = t.read(); } // Read end of tag/close bool done = false; while (! done) { debugAssert(n.type() == Token::SYMBOL); if (n.string() == "/") { // empty-element tag: <foo/> // Consume the close tag t.readSymbol(">"); done = true; } else if (n.string() == ">") { // End of open tag: read children until close tag while (! atClose(t, m_name)) { m_child.next().deserialize(t); } // Read close tag (we wouldn't be here unless it parses correctly) while (t.hasMore() && ! (t.readSymbol() == ">")) {} done = true; } else { // Attribute pair std::string k = n.string(); t.readSymbol("="); std::string v = t.read().string(); m_attribute.set(k, v); // Advance to next n = t.read(); } } } else { // Beginning embedded content. Read until the end of file or the next tag. m_type = VALUE; m_value += n.string(); n = t.peek(); while (t.hasMore() && ! ((n.type() == Token::SYMBOL) && (n.string() == "<"))) { m_value += " " + t.read().string(); n = t.peek(); } } }
void GPUProgram::BindingTable::parseVariable(TextInput& ti) { std::string name; // #var float4 osLight : : c[4] : 1 : 1 // #var float3 vin.v0 : $vin.POSITION : ATTR0 : 2 : 1 Token t = ti.peek(); if (t.type() != Token::SYMBOL) { goto abort; } // get the binding's type ti.readSymbol(); Type type; if (! CgType(t.string(), type)) { alwaysAssertM(false, std::string("Unsupported type: \"") + t.string() + "\""); } t = ti.peek(); if (t.type() != Token::SYMBOL) { goto abort; } // read the binding name name = ti.readSymbol(); if (! consumeSymbol(ti, ":")) { goto abort; } // see if it is the vertex or a constant register t = ti.peek(); if (t.type() != Token::SYMBOL) { goto abort; } // Sometimes there is an extra token between the colons if (t.string() != ":") { ti.readSymbol(); t = ti.peek(); } if (! consumeSymbol(ti, ":")) { goto abort; } // read the register number t = ti.peek(); if (t.type() != Token::SYMBOL) { goto abort; } // Consume the symbol we just peeked ti.readSymbol(); if (t.string() == "texunit") { // We're reading a texture unit } else if (t.string() == "c") { // We're reading a regular variable; parse the open bracket if (! consumeSymbol(ti, "[")) { goto abort; } } else if ((t.type() == Token::SYMBOL) && (t.string() == ":")) { // Unused variable; must be present but is not bound Binding binding; binding.source = VARIABLE; binding.type = type; binding.name = name; binding.slot = Binding::UNASSIGNED; bindingArray.append(binding); return; } else { // Something unexpected happened. goto abort; } t = ti.peek(); if (t.type() == Token::NUMBER) { int slot = iRound(ti.readNumber()); Binding binding; binding.source = VARIABLE; binding.type = type; binding.name = name; binding.slot = slot; bindingArray.append(binding); } abort: ;// Jump here if anything unexpected is encountered during parsing }