/* * Copyright 2009, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // // Driver function that sets up the Parser and Lexer for the "Technique" // grammar and executes the parsing process, returning the results as a // string and a Technique structure. // // Note that the "TechniqueParser.[c|h]" and "TechniqueLexer.[c|h]" files // are generated in standard C and compiled under C++, but the code // generator declares all functions as having "extern C" linkage. This may // lead to compiler warnings about returning "struct" type values from a // function - valid in C++, invalid under C. #include "base/logging.h" #include "compiler/technique/technique_parser.h" namespace o3d { // functions ------------------------------------------------------------------- // Use the Technique grammar to parse a UTF8 text file from the filesystem. bool ParseFxFile( const String& filename, String *shader_string, SamplerStateList *sampler_list, TechniqueDeclarationList *technique_list, String *error_string) { // Create the input stream object from a file of UTF8 held in the filesystem. // The antlr3 library requires a non-const pointer to the filename. char* temp = const_cast(filename.c_str()); pANTLR3_INPUT_STREAM input_stream = antlr3AsciiFileStreamNew( reinterpret_cast(temp)); if (input_stream == NULL) { DLOG(ERROR) << "Technique: Unable to open file" << filename << "due to memory allocation failure."; return false; } else { DLOG(INFO) << "Technique: Opened file \"" << filename << "\""; } // Create the language-specific Lexer. pTechniqueLexer lexer = TechniqueLexerNew(input_stream); if (lexer == NULL) { DLOG(ERROR) << "Technique: Unable to create the lexer"; input_stream->close(input_stream); return false; } else { DLOG(INFO) << "Technique: Created lexer."; } // Create token stream from the Lexer. pANTLR3_COMMON_TOKEN_STREAM token_stream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lexer)); if (token_stream == NULL) { DLOG(ERROR) << "Technique: failed to allocate token stream."; lexer->free(lexer); input_stream->close(input_stream); return false; } else { DLOG(INFO) << "Technique: Created token stream."; } // Force the token stream to turn off token filtering and pass all // whitespace and comments through to the parser. token_stream->discardOffChannel = ANTLR3_FALSE; // Create the language Parser. pTechniqueParser parser = TechniqueParserNew(token_stream); if (parser == NULL) { DLOG(ERROR) << "Technique: Out of memory trying to allocate parser"; token_stream->free(token_stream); lexer->free(lexer); input_stream->close(input_stream); return false; } else { DLOG(INFO) << "Technique: Created parser."; } // call the root parsing rule to parse the input stream. DLOG(INFO) << "Technique: Parsing..."; shader_string->clear(); technique_list->clear(); sampler_list->clear(); bool return_value = parser->translation_unit(parser, technique_list, sampler_list, shader_string, error_string); DLOG(INFO) << "Technique: Finished parsing."; DLOG(INFO) << "Technique: Shader string = "; DLOG(INFO) << *shader_string; // Free created objects. parser->free(parser); token_stream->free(token_stream); lexer->free(lexer); input_stream->close(input_stream); // Finished return return_value; } // Use the Technique grammar to parse an FX file from an in-memory, // zero-terminted UTF8 string buffer. bool ParseFxString( const String& fx_string, String *shader_string, SamplerStateList *sampler_list, TechniqueDeclarationList *technique_list, String* error_string) { // Create a token stream from a zero-terminated memory buffer of uint8. ANTLR3_UINT32 fx_string_length = static_cast(fx_string.length()); if (fx_string_length == 0) { DLOG(INFO) << "Technique: fx string has zero length. Skipping."; return true; } // Create the input stream from the memory buffer. // The antlr3 stream library requires a non-const pointer to the fx_string. char* temp_fx_string = const_cast(fx_string.c_str()); pANTLR3_INPUT_STREAM input_stream = antlr3NewAsciiStringInPlaceStream( reinterpret_cast(temp_fx_string), fx_string_length, NULL); if (input_stream == NULL) { DLOG(ERROR) << "Technique: Unable to create input stream from string."; return false; } else { DLOG(INFO) << "Technique: Created input stream from string."; } // Create the language-specific Lexer. pTechniqueLexer lexer = TechniqueLexerNew(input_stream); if (lexer == NULL) { DLOG(ERROR) << "Technique: Unable to create the lexer"; input_stream->close(input_stream); return false; } else { DLOG(INFO) << "Technique: Created lexer."; } // Create token stream from the Lexer. pANTLR3_COMMON_TOKEN_STREAM token_stream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lexer)); if (token_stream == NULL) { DLOG(ERROR) << "Technique: failed to allocate token stream."; lexer->free(lexer); input_stream->close(input_stream); return false; } else { DLOG(INFO) << "Technique: Created token stream."; } // Force the token stream to turn off token filtering and pass all // whitespace and comments through to the parser. token_stream->discardOffChannel = ANTLR3_FALSE; // Create the language Parser. pTechniqueParser parser = TechniqueParserNew(token_stream); if (parser == NULL) { DLOG(ERROR) << "Technique: Out of memory trying to allocate parser"; token_stream->free(token_stream); lexer->free(lexer); input_stream->close(input_stream); return false; } else { DLOG(INFO) << "Technique: Created parser."; } // call the root parsing rule to parse the input stream. DLOG(INFO) << "Technique: Parsing..."; shader_string->clear(); technique_list->clear(); sampler_list->clear(); bool return_value = parser->translation_unit(parser, technique_list, sampler_list, shader_string, error_string); DLOG(INFO) << "Technique: Finished parsing."; DLOG(INFO) << "Technique: Shader string = "; DLOG(INFO) << *shader_string; // Free created objects. parser->free(parser); token_stream->free(token_stream); lexer->free(lexer); input_stream->close(input_stream); // Completed return return_value; } } // namespace o3d